; (function (f) {
    if (typeof exports === 'object' && typeof module !== 'undefined') {
        module.exports = f()
    } else if (typeof define === 'function' && define.amd) {
        define([], f)
    } else {
        var g
        if (typeof window !== 'undefined') {
            g = window
        } else if (typeof global !== 'undefined') {
            g = global
        } else if (typeof self !== 'undefined') {
            g = self
        } else {
            g = this
        }
        g.adapter = f()
    }
})(function () {
    var define, module, exports
    return (function () {
        function r(e, n, t) {
            function o(i, f) {
                if (!n[i]) {
                    if (!e[i]) {
                        var c = 'function' == typeof require && require
                        if (!f && c) {
                            return c(i, !0)
                        }
                        if (u) {
                            return u(i, !0)
                        }
                        var a = new Error("Cannot find module '" + i + "'")
                        throw ((a.code = 'MODULE_NOT_FOUND'), a)
                    }
                    var p = (n[i] = { exports: {} })
                    e[i][0].call(
                        p.exports,
                        function (r) {
                            var n = e[i][1][r]
                            return o(n || r)
                        },
                        p,
                        p.exports,
                        r,
                        e,
                        n,
                        t
                    )
                }
                return n[i].exports
            }
            for (var u = 'function' == typeof require && require, i = 0; i < t.length; i++) {
                o(t[i])
            }
            return o
        }
        return r
    })()(
        {
            1: [
                function (require, module, exports) {
                    /*
                     *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
                     *
                     *  Use of this source code is governed by a BSD-style license
                     *  that can be found in the LICENSE file in the root of the source
                     *  tree.
                     */
                    /* eslint-env node */

                    'use strict'

                    var _adapter_factory = require('./adapter_factory.js')

                    var adapter = (0, _adapter_factory.adapterFactory)({
                        window: typeof window === 'undefined' ? undefined : window
                    })
                    module.exports = adapter // this is the difference from adapter_core.
                },
                { './adapter_factory.js': 2 }
            ],
            2: [
                function (require, module, exports) {
                    'use strict'

                    Object.defineProperty(exports, '__esModule', {
                        value: true
                    })
                    exports.adapterFactory = adapterFactory

                    var _utils = require('./utils')

                    var utils = _interopRequireWildcard(_utils)

                    var _chrome_shim = require('./chrome/chrome_shim')

                    var chromeShim = _interopRequireWildcard(_chrome_shim)

                    var _firefox_shim = require('./firefox/firefox_shim')

                    var firefoxShim = _interopRequireWildcard(_firefox_shim)

                    var _safari_shim = require('./safari/safari_shim')

                    var safariShim = _interopRequireWildcard(_safari_shim)

                    var _common_shim = require('./common_shim')

                    var commonShim = _interopRequireWildcard(_common_shim)

                    var _sdp = require('sdp')

                    var sdp = _interopRequireWildcard(_sdp)

                    function _interopRequireWildcard(obj) {
                        if (obj && obj.__esModule) {
                            return obj
                        } else {
                            var newObj = {}
                            if (obj != null) {
                                for (var key in obj) {
                                    if (Object.prototype.hasOwnProperty.call(obj, key)) {
                                        newObj[key] = obj[key]
                                    }
                                }
                            }
                            newObj.default = obj
                            return newObj
                        }
                    }

                    // Shimming starts here.
                    /*
                     *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
                     *
                     *  Use of this source code is governed by a BSD-style license
                     *  that can be found in the LICENSE file in the root of the source
                     *  tree.
                     */
                    function adapterFactory() {
                        var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
                            window = _ref.window

                        var options =
                            arguments.length > 1 && arguments[1] !== undefined
                                ? arguments[1]
                                : {
                                    shimChrome: true,
                                    shimFirefox: true,
                                    shimSafari: true
                                }

                        // Utils.
                        var logging = utils.log
                        var browserDetails = utils.detectBrowser(window)

                        var adapter = {
                            browserDetails: browserDetails,
                            commonShim: commonShim,
                            extractVersion: utils.extractVersion,
                            disableLog: utils.disableLog,
                            disableWarnings: utils.disableWarnings,
                            // Expose sdp as a convenience. For production apps include directly.
                            sdp: sdp
                        }

                        // Shim browser if found.
                        switch (browserDetails.browser) {
                            case 'chrome':
                                if (!chromeShim || !chromeShim.shimPeerConnection || !options.shimChrome) {
                                    logging('Chrome shim is not included in this adapter release.')
                                    return adapter
                                }
                                if (browserDetails.version === null) {
                                    logging('Chrome shim can not determine version, not shimming.')
                                    return adapter
                                }
                                logging('adapter.js shimming chrome.')
                                // Export to the adapter global object visible in the browser.
                                adapter.browserShim = chromeShim

                                // Must be called before shimPeerConnection.
                                commonShim.shimAddIceCandidateNullOrEmpty(window, browserDetails)
                                commonShim.shimParameterlessSetLocalDescription(window, browserDetails)

                                chromeShim.shimGetUserMedia(window, browserDetails)
                                chromeShim.shimMediaStream(window, browserDetails)
                                chromeShim.shimPeerConnection(window, browserDetails)
                                chromeShim.shimOnTrack(window, browserDetails)
                                chromeShim.shimAddTrackRemoveTrack(window, browserDetails)
                                chromeShim.shimGetSendersWithDtmf(window, browserDetails)
                                chromeShim.shimGetStats(window, browserDetails)
                                chromeShim.shimSenderReceiverGetStats(window, browserDetails)
                                chromeShim.fixNegotiationNeeded(window, browserDetails)

                                commonShim.shimRTCIceCandidate(window, browserDetails)
                                commonShim.shimRTCIceCandidateRelayProtocol(window, browserDetails)
                                commonShim.shimConnectionState(window, browserDetails)
                                commonShim.shimMaxMessageSize(window, browserDetails)
                                commonShim.shimSendThrowTypeError(window, browserDetails)
                                commonShim.removeExtmapAllowMixed(window, browserDetails)
                                break
                            case 'firefox':
                                if (!firefoxShim || !firefoxShim.shimPeerConnection || !options.shimFirefox) {
                                    logging('Firefox shim is not included in this adapter release.')
                                    return adapter
                                }
                                logging('adapter.js shimming firefox.')
                                // Export to the adapter global object visible in the browser.
                                adapter.browserShim = firefoxShim

                                // Must be called before shimPeerConnection.
                                commonShim.shimAddIceCandidateNullOrEmpty(window, browserDetails)
                                commonShim.shimParameterlessSetLocalDescription(window, browserDetails)

                                firefoxShim.shimGetUserMedia(window, browserDetails)
                                firefoxShim.shimPeerConnection(window, browserDetails)
                                firefoxShim.shimOnTrack(window, browserDetails)
                                firefoxShim.shimRemoveStream(window, browserDetails)
                                firefoxShim.shimSenderGetStats(window, browserDetails)
                                firefoxShim.shimReceiverGetStats(window, browserDetails)
                                firefoxShim.shimRTCDataChannel(window, browserDetails)
                                firefoxShim.shimAddTransceiver(window, browserDetails)
                                firefoxShim.shimGetParameters(window, browserDetails)
                                firefoxShim.shimCreateOffer(window, browserDetails)
                                firefoxShim.shimCreateAnswer(window, browserDetails)

                                commonShim.shimRTCIceCandidate(window, browserDetails)
                                commonShim.shimConnectionState(window, browserDetails)
                                commonShim.shimMaxMessageSize(window, browserDetails)
                                commonShim.shimSendThrowTypeError(window, browserDetails)
                                break
                            case 'safari':
                                if (!safariShim || !options.shimSafari) {
                                    logging('Safari shim is not included in this adapter release.')
                                    return adapter
                                }
                                logging('adapter.js shimming safari.')
                                // Export to the adapter global object visible in the browser.
                                adapter.browserShim = safariShim

                                // Must be called before shimCallbackAPI.
                                commonShim.shimAddIceCandidateNullOrEmpty(window, browserDetails)
                                commonShim.shimParameterlessSetLocalDescription(window, browserDetails)

                                safariShim.shimRTCIceServerUrls(window, browserDetails)
                                safariShim.shimCreateOfferLegacy(window, browserDetails)
                                safariShim.shimCallbacksAPI(window, browserDetails)
                                safariShim.shimLocalStreamsAPI(window, browserDetails)
                                safariShim.shimRemoteStreamsAPI(window, browserDetails)
                                safariShim.shimTrackEventTransceiver(window, browserDetails)
                                safariShim.shimGetUserMedia(window, browserDetails)
                                safariShim.shimAudioContext(window, browserDetails)

                                commonShim.shimRTCIceCandidate(window, browserDetails)
                                commonShim.shimRTCIceCandidateRelayProtocol(window, browserDetails)
                                commonShim.shimMaxMessageSize(window, browserDetails)
                                commonShim.shimSendThrowTypeError(window, browserDetails)
                                commonShim.removeExtmapAllowMixed(window, browserDetails)
                                break
                            default:
                                logging('Unsupported browser!')
                                break
                        }

                        return adapter
                    }

                    // Browser shims.
                },
                {
                    './chrome/chrome_shim': 3,
                    './common_shim': 6,
                    './firefox/firefox_shim': 7,
                    './safari/safari_shim': 10,
                    './utils': 11,
                    sdp: 12
                }
            ],
            3: [
                function (require, module, exports) {
                    /*
                     *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
                     *
                     *  Use of this source code is governed by a BSD-style license
                     *  that can be found in the LICENSE file in the root of the source
                     *  tree.
                     */
                    /* eslint-env node */
                    'use strict'

                    Object.defineProperty(exports, '__esModule', {
                        value: true
                    })
                    exports.shimGetDisplayMedia = exports.shimGetUserMedia = undefined

                    var _typeof =
                        typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol'
                            ? function (obj) {
                                return typeof obj
                            }
                            : function (obj) {
                                return obj &&
                                    typeof Symbol === 'function' &&
                                    obj.constructor === Symbol &&
                                    obj !== Symbol.prototype
                                    ? 'symbol'
                                    : typeof obj
                            }

                    var _getusermedia = require('./getusermedia')

                    Object.defineProperty(exports, 'shimGetUserMedia', {
                        enumerable: true,
                        get: function get() {
                            return _getusermedia.shimGetUserMedia
                        }
                    })

                    var _getdisplaymedia = require('./getdisplaymedia')

                    Object.defineProperty(exports, 'shimGetDisplayMedia', {
                        enumerable: true,
                        get: function get() {
                            return _getdisplaymedia.shimGetDisplayMedia
                        }
                    })
                    exports.shimMediaStream = shimMediaStream
                    exports.shimOnTrack = shimOnTrack
                    exports.shimGetSendersWithDtmf = shimGetSendersWithDtmf
                    exports.shimGetStats = shimGetStats
                    exports.shimSenderReceiverGetStats = shimSenderReceiverGetStats
                    exports.shimAddTrackRemoveTrackWithNative = shimAddTrackRemoveTrackWithNative
                    exports.shimAddTrackRemoveTrack = shimAddTrackRemoveTrack
                    exports.shimPeerConnection = shimPeerConnection
                    exports.fixNegotiationNeeded = fixNegotiationNeeded

                    var _utils = require('../utils.js')

                    var utils = _interopRequireWildcard(_utils)

                    function _interopRequireWildcard(obj) {
                        if (obj && obj.__esModule) {
                            return obj
                        } else {
                            var newObj = {}
                            if (obj != null) {
                                for (var key in obj) {
                                    if (Object.prototype.hasOwnProperty.call(obj, key)) {
                                        newObj[key] = obj[key]
                                    }
                                }
                            }
                            newObj.default = obj
                            return newObj
                        }
                    }

                    function _defineProperty(obj, key, value) {
                        if (key in obj) {
                            Object.defineProperty(obj, key, {
                                value: value,
                                enumerable: true,
                                configurable: true,
                                writable: true
                            })
                        } else {
                            obj[key] = value
                        }
                        return obj
                    }

                    function shimMediaStream(window) {
                        window.MediaStream = window.MediaStream || window.webkitMediaStream
                    }

                    function shimOnTrack(window) {
                        if (
                            (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' &&
                            window.RTCPeerConnection &&
                            !('ontrack' in window.RTCPeerConnection.prototype)
                        ) {
                            Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
                                get: function get() {
                                    return this._ontrack
                                },
                                set: function set(f) {
                                    if (this._ontrack) {
                                        this.removeEventListener('track', this._ontrack)
                                    }
                                    this.addEventListener('track', (this._ontrack = f))
                                },

                                enumerable: true,
                                configurable: true
                            })
                            var origSetRemoteDescription = window.RTCPeerConnection.prototype.setRemoteDescription
                            window.RTCPeerConnection.prototype.setRemoteDescription =
                                function setRemoteDescription() {
                                    var _this = this

                                    if (!this._ontrackpoly) {
                                        this._ontrackpoly = function (e) {
                                            // onaddstream does not fire when a track is added to an existing
                                            // stream. But stream.onaddtrack is implemented so we use that.
                                            e.stream.addEventListener('addtrack', function (te) {
                                                var receiver = void 0
                                                if (window.RTCPeerConnection.prototype.getReceivers) {
                                                    receiver = _this.getReceivers().find(function (r) {
                                                        return r.track && r.track.id === te.track.id
                                                    })
                                                } else {
                                                    receiver = { track: te.track }
                                                }

                                                var event = new Event('track')
                                                event.track = te.track
                                                event.receiver = receiver
                                                event.transceiver = { receiver: receiver }
                                                event.streams = [e.stream]
                                                _this.dispatchEvent(event)
                                            })
                                            e.stream.getTracks().forEach(function (track) {
                                                var receiver = void 0
                                                if (window.RTCPeerConnection.prototype.getReceivers) {
                                                    receiver = _this.getReceivers().find(function (r) {
                                                        return r.track && r.track.id === track.id
                                                    })
                                                } else {
                                                    receiver = { track: track }
                                                }
                                                var event = new Event('track')
                                                event.track = track
                                                event.receiver = receiver
                                                event.transceiver = { receiver: receiver }
                                                event.streams = [e.stream]
                                                _this.dispatchEvent(event)
                                            })
                                        }
                                        this.addEventListener('addstream', this._ontrackpoly)
                                    }
                                    return origSetRemoteDescription.apply(this, arguments)
                                }
                        } else {
                            // even if RTCRtpTransceiver is in window, it is only used and
                            // emitted in unified-plan. Unfortunately this means we need
                            // to unconditionally wrap the event.
                            utils.wrapPeerConnectionEvent(window, 'track', function (e) {
                                if (!e.transceiver) {
                                    Object.defineProperty(e, 'transceiver', { value: { receiver: e.receiver } })
                                }
                                return e
                            })
                        }
                    }

                    function shimGetSendersWithDtmf(window) {
                        // Overrides addTrack/removeTrack, depends on shimAddTrackRemoveTrack.
                        if (
                            (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' &&
                            window.RTCPeerConnection &&
                            !('getSenders' in window.RTCPeerConnection.prototype) &&
                            'createDTMFSender' in window.RTCPeerConnection.prototype
                        ) {
                            var shimSenderWithDtmf = function shimSenderWithDtmf(pc, track) {
                                return {
                                    track: track,
                                    get dtmf() {
                                        if (this._dtmf === undefined) {
                                            if (track.kind === 'audio') {
                                                this._dtmf = pc.createDTMFSender(track)
                                            } else {
                                                this._dtmf = null
                                            }
                                        }
                                        return this._dtmf
                                    },
                                    _pc: pc
                                }
                            }

                            // augment addTrack when getSenders is not available.
                            if (!window.RTCPeerConnection.prototype.getSenders) {
                                window.RTCPeerConnection.prototype.getSenders = function getSenders() {
                                    this._senders = this._senders || []
                                    return this._senders.slice() // return a copy of the internal state.
                                }
                                var origAddTrack = window.RTCPeerConnection.prototype.addTrack
                                window.RTCPeerConnection.prototype.addTrack = function addTrack(track, stream) {
                                    var sender = origAddTrack.apply(this, arguments)
                                    if (!sender) {
                                        sender = shimSenderWithDtmf(this, track)
                                        this._senders.push(sender)
                                    }
                                    return sender
                                }

                                var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack
                                window.RTCPeerConnection.prototype.removeTrack = function removeTrack(sender) {
                                    origRemoveTrack.apply(this, arguments)
                                    var idx = this._senders.indexOf(sender)
                                    if (idx !== -1) {
                                        this._senders.splice(idx, 1)
                                    }
                                }
                            }
                            var origAddStream = window.RTCPeerConnection.prototype.addStream
                            window.RTCPeerConnection.prototype.addStream = function addStream(stream) {
                                var _this2 = this

                                this._senders = this._senders || []
                                origAddStream.apply(this, [stream])
                                stream.getTracks().forEach(function (track) {
                                    _this2._senders.push(shimSenderWithDtmf(_this2, track))
                                })
                            }

                            var origRemoveStream = window.RTCPeerConnection.prototype.removeStream
                            window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) {
                                var _this3 = this

                                this._senders = this._senders || []
                                origRemoveStream.apply(this, [stream])

                                stream.getTracks().forEach(function (track) {
                                    var sender = _this3._senders.find(function (s) {
                                        return s.track === track
                                    })
                                    if (sender) {
                                        // remove sender
                                        _this3._senders.splice(_this3._senders.indexOf(sender), 1)
                                    }
                                })
                            }
                        } else if (
                            (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' &&
                            window.RTCPeerConnection &&
                            'getSenders' in window.RTCPeerConnection.prototype &&
                            'createDTMFSender' in window.RTCPeerConnection.prototype &&
                            window.RTCRtpSender &&
                            !('dtmf' in window.RTCRtpSender.prototype)
                        ) {
                            var origGetSenders = window.RTCPeerConnection.prototype.getSenders
                            window.RTCPeerConnection.prototype.getSenders = function getSenders() {
                                var _this4 = this

                                var senders = origGetSenders.apply(this, [])
                                senders.forEach(function (sender) {
                                    return (sender._pc = _this4)
                                })
                                return senders
                            }

                            Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {
                                get: function get() {
                                    if (this._dtmf === undefined) {
                                        if (this.track.kind === 'audio') {
                                            this._dtmf = this._pc.createDTMFSender(this.track)
                                        } else {
                                            this._dtmf = null
                                        }
                                    }
                                    return this._dtmf
                                }
                            })
                        }
                    }

                    function shimGetStats(window) {
                        if (!window.RTCPeerConnection) {
                            return
                        }

                        var origGetStats = window.RTCPeerConnection.prototype.getStats
                        window.RTCPeerConnection.prototype.getStats = function getStats() {
                            var _this5 = this

                            var _arguments = Array.prototype.slice.call(arguments),
                                selector = _arguments[0],
                                onSucc = _arguments[1],
                                onErr = _arguments[2]

                            // If selector is a function then we are in the old style stats so just
                            // pass back the original getStats format to avoid breaking old users.

                            if (arguments.length > 0 && typeof selector === 'function') {
                                return origGetStats.apply(this, arguments)
                            }

                            // When spec-style getStats is supported, return those when called with
                            // either no arguments or the selector argument is null.
                            if (
                                origGetStats.length === 0 &&
                                (arguments.length === 0 || typeof selector !== 'function')
                            ) {
                                return origGetStats.apply(this, [])
                            }

                            var fixChromeStats_ = function fixChromeStats_(response) {
                                var standardReport = {}
                                var reports = response.result()
                                reports.forEach(function (report) {
                                    var standardStats = {
                                        id: report.id,
                                        timestamp: report.timestamp,
                                        type:
                                            {
                                                localcandidate: 'local-candidate',
                                                remotecandidate: 'remote-candidate'
                                            }[report.type] || report.type
                                    }
                                    report.names().forEach(function (name) {
                                        standardStats[name] = report.stat(name)
                                    })
                                    standardReport[standardStats.id] = standardStats
                                })

                                return standardReport
                            }

                            // shim getStats with maplike support
                            var makeMapStats = function makeMapStats(stats) {
                                return new Map(
                                    Object.keys(stats).map(function (key) {
                                        return [key, stats[key]]
                                    })
                                )
                            }

                            if (arguments.length >= 2) {
                                var successCallbackWrapper_ = function successCallbackWrapper_(response) {
                                    onSucc(makeMapStats(fixChromeStats_(response)))
                                }

                                return origGetStats.apply(this, [successCallbackWrapper_, selector])
                            }

                            // promise-support
                            return new Promise(function (resolve, reject) {
                                origGetStats.apply(_this5, [
                                    function (response) {
                                        resolve(makeMapStats(fixChromeStats_(response)))
                                    },
                                    reject
                                ])
                            }).then(onSucc, onErr)
                        }
                    }

                    function shimSenderReceiverGetStats(window) {
                        if (
                            !(
                                (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' &&
                                window.RTCPeerConnection &&
                                window.RTCRtpSender &&
                                window.RTCRtpReceiver
                            )
                        ) {
                            return
                        }

                        // shim sender stats.
                        if (!('getStats' in window.RTCRtpSender.prototype)) {
                            var origGetSenders = window.RTCPeerConnection.prototype.getSenders
                            if (origGetSenders) {
                                window.RTCPeerConnection.prototype.getSenders = function getSenders() {
                                    var _this6 = this

                                    var senders = origGetSenders.apply(this, [])
                                    senders.forEach(function (sender) {
                                        return (sender._pc = _this6)
                                    })
                                    return senders
                                }
                            }

                            var origAddTrack = window.RTCPeerConnection.prototype.addTrack
                            if (origAddTrack) {
                                window.RTCPeerConnection.prototype.addTrack = function addTrack() {
                                    var sender = origAddTrack.apply(this, arguments)
                                    sender._pc = this
                                    return sender
                                }
                            }
                            window.RTCRtpSender.prototype.getStats = function getStats() {
                                var sender = this
                                return this._pc.getStats().then(function (result) {
                                    return (
                                        /* Note: this will include stats of all senders that
                                         *   send a track with the same id as sender.track as
                                         *   it is not possible to identify the RTCRtpSender.
                                         */
                                        utils.filterStats(result, sender.track, true)
                                    )
                                })
                            }
                        }

                        // shim receiver stats.
                        if (!('getStats' in window.RTCRtpReceiver.prototype)) {
                            var origGetReceivers = window.RTCPeerConnection.prototype.getReceivers
                            if (origGetReceivers) {
                                window.RTCPeerConnection.prototype.getReceivers = function getReceivers() {
                                    var _this7 = this

                                    var receivers = origGetReceivers.apply(this, [])
                                    receivers.forEach(function (receiver) {
                                        return (receiver._pc = _this7)
                                    })
                                    return receivers
                                }
                            }
                            utils.wrapPeerConnectionEvent(window, 'track', function (e) {
                                e.receiver._pc = e.srcElement
                                return e
                            })
                            window.RTCRtpReceiver.prototype.getStats = function getStats() {
                                var receiver = this
                                return this._pc.getStats().then(function (result) {
                                    return utils.filterStats(result, receiver.track, false)
                                })
                            }
                        }

                        if (
                            !(
                                'getStats' in window.RTCRtpSender.prototype &&
                                'getStats' in window.RTCRtpReceiver.prototype
                            )
                        ) {
                            return
                        }

                        // shim RTCPeerConnection.getStats(track).
                        var origGetStats = window.RTCPeerConnection.prototype.getStats
                        window.RTCPeerConnection.prototype.getStats = function getStats() {
                            if (arguments.length > 0 && arguments[0] instanceof window.MediaStreamTrack) {
                                var track = arguments[0]
                                var sender = void 0
                                var receiver = void 0
                                var err = void 0
                                this.getSenders().forEach(function (s) {
                                    if (s.track === track) {
                                        if (sender) {
                                            err = true
                                        } else {
                                            sender = s
                                        }
                                    }
                                })
                                this.getReceivers().forEach(function (r) {
                                    if (r.track === track) {
                                        if (receiver) {
                                            err = true
                                        } else {
                                            receiver = r
                                        }
                                    }
                                    return r.track === track
                                })
                                if (err || (sender && receiver)) {
                                    return Promise.reject(
                                        new DOMException(
                                            'There are more than one sender or receiver for the track.',
                                            'InvalidAccessError'
                                        )
                                    )
                                } else if (sender) {
                                    return sender.getStats()
                                } else if (receiver) {
                                    return receiver.getStats()
                                }
                                return Promise.reject(
                                    new DOMException(
                                        'There is no sender or receiver for the track.',
                                        'InvalidAccessError'
                                    )
                                )
                            }
                            return origGetStats.apply(this, arguments)
                        }
                    }

                    function shimAddTrackRemoveTrackWithNative(window) {
                        // shim addTrack/removeTrack with native variants in order to make
                        // the interactions with legacy getLocalStreams behave as in other browsers.
                        // Keeps a mapping stream.id => [stream, rtpsenders...]
                        window.RTCPeerConnection.prototype.getLocalStreams = function getLocalStreams() {
                            var _this8 = this

                            this._shimmedLocalStreams = this._shimmedLocalStreams || {}
                            return Object.keys(this._shimmedLocalStreams).map(function (streamId) {
                                return _this8._shimmedLocalStreams[streamId][0]
                            })
                        }

                        var origAddTrack = window.RTCPeerConnection.prototype.addTrack
                        window.RTCPeerConnection.prototype.addTrack = function addTrack(track, stream) {
                            if (!stream) {
                                return origAddTrack.apply(this, arguments)
                            }
                            this._shimmedLocalStreams = this._shimmedLocalStreams || {}

                            var sender = origAddTrack.apply(this, arguments)
                            if (!this._shimmedLocalStreams[stream.id]) {
                                this._shimmedLocalStreams[stream.id] = [stream, sender]
                            } else if (this._shimmedLocalStreams[stream.id].indexOf(sender) === -1) {
                                this._shimmedLocalStreams[stream.id].push(sender)
                            }
                            return sender
                        }

                        var origAddStream = window.RTCPeerConnection.prototype.addStream
                        window.RTCPeerConnection.prototype.addStream = function addStream(stream) {
                            var _this9 = this

                            this._shimmedLocalStreams = this._shimmedLocalStreams || {}

                            stream.getTracks().forEach(function (track) {
                                var alreadyExists = _this9.getSenders().find(function (s) {
                                    return s.track === track
                                })
                                if (alreadyExists) {
                                    throw new DOMException('Track already exists.', 'InvalidAccessError')
                                }
                            })
                            var existingSenders = this.getSenders()
                            origAddStream.apply(this, arguments)
                            var newSenders = this.getSenders().filter(function (newSender) {
                                return existingSenders.indexOf(newSender) === -1
                            })
                            this._shimmedLocalStreams[stream.id] = [stream].concat(newSenders)
                        }

                        var origRemoveStream = window.RTCPeerConnection.prototype.removeStream
                        window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) {
                            this._shimmedLocalStreams = this._shimmedLocalStreams || {}
                            delete this._shimmedLocalStreams[stream.id]
                            return origRemoveStream.apply(this, arguments)
                        }

                        var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack
                        window.RTCPeerConnection.prototype.removeTrack = function removeTrack(sender) {
                            var _this10 = this

                            this._shimmedLocalStreams = this._shimmedLocalStreams || {}
                            if (sender) {
                                Object.keys(this._shimmedLocalStreams).forEach(function (streamId) {
                                    var idx = _this10._shimmedLocalStreams[streamId].indexOf(sender)
                                    if (idx !== -1) {
                                        _this10._shimmedLocalStreams[streamId].splice(idx, 1)
                                    }
                                    if (_this10._shimmedLocalStreams[streamId].length === 1) {
                                        delete _this10._shimmedLocalStreams[streamId]
                                    }
                                })
                            }
                            return origRemoveTrack.apply(this, arguments)
                        }
                    }

                    function shimAddTrackRemoveTrack(window, browserDetails) {
                        if (!window.RTCPeerConnection) {
                            return
                        }
                        // shim addTrack and removeTrack.
                        if (window.RTCPeerConnection.prototype.addTrack && browserDetails.version >= 65) {
                            return shimAddTrackRemoveTrackWithNative(window)
                        }

                        // also shim pc.getLocalStreams when addTrack is shimmed
                        // to return the original streams.
                        var origGetLocalStreams = window.RTCPeerConnection.prototype.getLocalStreams
                        window.RTCPeerConnection.prototype.getLocalStreams = function getLocalStreams() {
                            var _this11 = this

                            var nativeStreams = origGetLocalStreams.apply(this)
                            this._reverseStreams = this._reverseStreams || {}
                            return nativeStreams.map(function (stream) {
                                return _this11._reverseStreams[stream.id]
                            })
                        }

                        var origAddStream = window.RTCPeerConnection.prototype.addStream
                        window.RTCPeerConnection.prototype.addStream = function addStream(stream) {
                            var _this12 = this

                            this._streams = this._streams || {}
                            this._reverseStreams = this._reverseStreams || {}

                            stream.getTracks().forEach(function (track) {
                                var alreadyExists = _this12.getSenders().find(function (s) {
                                    return s.track === track
                                })
                                if (alreadyExists) {
                                    throw new DOMException('Track already exists.', 'InvalidAccessError')
                                }
                            })
                            // Add identity mapping for consistency with addTrack.
                            // Unless this is being used with a stream from addTrack.
                            if (!this._reverseStreams[stream.id]) {
                                var newStream = new window.MediaStream(stream.getTracks())
                                this._streams[stream.id] = newStream
                                this._reverseStreams[newStream.id] = stream
                                stream = newStream
                            }
                            origAddStream.apply(this, [stream])
                        }

                        var origRemoveStream = window.RTCPeerConnection.prototype.removeStream
                        window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) {
                            this._streams = this._streams || {}
                            this._reverseStreams = this._reverseStreams || {}

                            origRemoveStream.apply(this, [this._streams[stream.id] || stream])
                            delete this._reverseStreams[
                                this._streams[stream.id] ? this._streams[stream.id].id : stream.id
                            ]
                            delete this._streams[stream.id]
                        }

                        window.RTCPeerConnection.prototype.addTrack = function addTrack(track, stream) {
                            var _this13 = this

                            if (this.signalingState === 'closed') {
                                throw new DOMException(
                                    "The RTCPeerConnection's signalingState is 'closed'.",
                                    'InvalidStateError'
                                )
                            }
                            var streams = [].slice.call(arguments, 1)
                            if (
                                streams.length !== 1 ||
                                !streams[0].getTracks().find(function (t) {
                                    return t === track
                                })
                            ) {
                                // this is not fully correct but all we can manage without
                                // [[associated MediaStreams]] internal slot.
                                throw new DOMException(
                                    'The adapter.js addTrack polyfill only supports a single ' +
                                    ' stream which is associated with the specified track.',
                                    'NotSupportedError'
                                )
                            }

                            var alreadyExists = this.getSenders().find(function (s) {
                                return s.track === track
                            })
                            if (alreadyExists) {
                                throw new DOMException('Track already exists.', 'InvalidAccessError')
                            }

                            this._streams = this._streams || {}
                            this._reverseStreams = this._reverseStreams || {}
                            var oldStream = this._streams[stream.id]
                            if (oldStream) {
                                // this is using odd Chrome behaviour, use with caution:
                                // https://bugs.chromium.org/p/webrtc/issues/detail?id=7815
                                // Note: we rely on the high-level addTrack/dtmf shim to
                                // create the sender with a dtmf sender.
                                oldStream.addTrack(track)

                                // Trigger ONN async.
                                Promise.resolve().then(function () {
                                    _this13.dispatchEvent(new Event('negotiationneeded'))
                                })
                            } else {
                                var newStream = new window.MediaStream([track])
                                this._streams[stream.id] = newStream
                                this._reverseStreams[newStream.id] = stream
                                this.addStream(newStream)
                            }
                            return this.getSenders().find(function (s) {
                                return s.track === track
                            })
                        }

                        // replace the internal stream id with the external one and
                        // vice versa.
                        function replaceInternalStreamId(pc, description) {
                            var sdp = description.sdp
                            Object.keys(pc._reverseStreams || []).forEach(function (internalId) {
                                var externalStream = pc._reverseStreams[internalId]
                                var internalStream = pc._streams[externalStream.id]
                                sdp = sdp.replace(new RegExp(internalStream.id, 'g'), externalStream.id)
                            })
                            return new RTCSessionDescription({
                                type: description.type,
                                sdp: sdp
                            })
                        }
                        function replaceExternalStreamId(pc, description) {
                            var sdp = description.sdp
                            Object.keys(pc._reverseStreams || []).forEach(function (internalId) {
                                var externalStream = pc._reverseStreams[internalId]
                                var internalStream = pc._streams[externalStream.id]
                                sdp = sdp.replace(new RegExp(externalStream.id, 'g'), internalStream.id)
                            })
                            return new RTCSessionDescription({
                                type: description.type,
                                sdp: sdp
                            })
                        }
                        ;['createOffer', 'createAnswer'].forEach(function (method) {
                            var nativeMethod = window.RTCPeerConnection.prototype[method]
                            var methodObj = _defineProperty({}, method, function () {
                                var _this14 = this

                                var args = arguments
                                var isLegacyCall = arguments.length && typeof arguments[0] === 'function'
                                if (isLegacyCall) {
                                    return nativeMethod.apply(this, [
                                        function (description) {
                                            var desc = replaceInternalStreamId(_this14, description)
                                            args[0].apply(null, [desc])
                                        },
                                        function (err) {
                                            if (args[1]) {
                                                args[1].apply(null, err)
                                            }
                                        },
                                        arguments[2]
                                    ])
                                }
                                return nativeMethod.apply(this, arguments).then(function (description) {
                                    return replaceInternalStreamId(_this14, description)
                                })
                            })
                            window.RTCPeerConnection.prototype[method] = methodObj[method]
                        })

                        var origSetLocalDescription = window.RTCPeerConnection.prototype.setLocalDescription
                        window.RTCPeerConnection.prototype.setLocalDescription =
                            function setLocalDescription() {
                                if (!arguments.length || !arguments[0].type) {
                                    return origSetLocalDescription.apply(this, arguments)
                                }
                                arguments[0] = replaceExternalStreamId(this, arguments[0])
                                return origSetLocalDescription.apply(this, arguments)
                            }

                        // TODO: mangle getStats: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamstats-streamidentifier

                        var origLocalDescription = Object.getOwnPropertyDescriptor(
                            window.RTCPeerConnection.prototype,
                            'localDescription'
                        )
                        Object.defineProperty(window.RTCPeerConnection.prototype, 'localDescription', {
                            get: function get() {
                                var description = origLocalDescription.get.apply(this)
                                if (description.type === '') {
                                    return description
                                }
                                return replaceInternalStreamId(this, description)
                            }
                        })

                        window.RTCPeerConnection.prototype.removeTrack = function removeTrack(sender) {
                            var _this15 = this

                            if (this.signalingState === 'closed') {
                                throw new DOMException(
                                    "The RTCPeerConnection's signalingState is 'closed'.",
                                    'InvalidStateError'
                                )
                            }
                            // We can not yet check for sender instanceof RTCRtpSender
                            // since we shim RTPSender. So we check if sender._pc is set.
                            if (!sender._pc) {
                                throw new DOMException(
                                    'Argument 1 of RTCPeerConnection.removeTrack ' +
                                    'does not implement interface RTCRtpSender.',
                                    'TypeError'
                                )
                            }
                            var isLocal = sender._pc === this
                            if (!isLocal) {
                                throw new DOMException(
                                    'Sender was not created by this connection.',
                                    'InvalidAccessError'
                                )
                            }

                            // Search for the native stream the senders track belongs to.
                            this._streams = this._streams || {}
                            var stream = void 0
                            Object.keys(this._streams).forEach(function (streamid) {
                                var hasTrack = _this15._streams[streamid].getTracks().find(function (track) {
                                    return sender.track === track
                                })
                                if (hasTrack) {
                                    stream = _this15._streams[streamid]
                                }
                            })

                            if (stream) {
                                if (stream.getTracks().length === 1) {
                                    // if this is the last track of the stream, remove the stream. This
                                    // takes care of any shimmed _senders.
                                    this.removeStream(this._reverseStreams[stream.id])
                                } else {
                                    // relying on the same odd chrome behaviour as above.
                                    stream.removeTrack(sender.track)
                                }
                                this.dispatchEvent(new Event('negotiationneeded'))
                            }
                        }
                    }

                    function shimPeerConnection(window, browserDetails) {
                        if (!window.RTCPeerConnection && window.webkitRTCPeerConnection) {
                            // very basic support for old versions.
                            window.RTCPeerConnection = window.webkitRTCPeerConnection
                        }
                        if (!window.RTCPeerConnection) {
                            return
                        }

                        // shim implicit creation of RTCSessionDescription/RTCIceCandidate
                        if (browserDetails.version < 53) {
                            ;['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'].forEach(function (
                                method
                            ) {
                                var nativeMethod = window.RTCPeerConnection.prototype[method]
                                var methodObj = _defineProperty({}, method, function () {
                                    arguments[0] = new (
                                        method === 'addIceCandidate'
                                            ? window.RTCIceCandidate
                                            : window.RTCSessionDescription
                                    )(arguments[0])
                                    return nativeMethod.apply(this, arguments)
                                })
                                window.RTCPeerConnection.prototype[method] = methodObj[method]
                            })
                        }
                    }

                    // Attempt to fix ONN in plan-b mode.
                    function fixNegotiationNeeded(window, browserDetails) {
                        utils.wrapPeerConnectionEvent(window, 'negotiationneeded', function (e) {
                            var pc = e.target
                            if (
                                browserDetails.version < 72 ||
                                (pc.getConfiguration && pc.getConfiguration().sdpSemantics === 'plan-b')
                            ) {
                                if (pc.signalingState !== 'stable') {
                                    return
                                }
                            }
                            return e
                        })
                    }
                },
                { '../utils.js': 11, './getdisplaymedia': 4, './getusermedia': 5 }
            ],
            4: [
                function (require, module, exports) {
                    /*
                     *  Copyright (c) 2018 The adapter.js project authors. All Rights Reserved.
                     *
                     *  Use of this source code is governed by a BSD-style license
                     *  that can be found in the LICENSE file in the root of the source
                     *  tree.
                     */
                    /* eslint-env node */
                    'use strict'

                    Object.defineProperty(exports, '__esModule', {
                        value: true
                    })
                    exports.shimGetDisplayMedia = shimGetDisplayMedia
                    function shimGetDisplayMedia(window, getSourceId) {
                        if (
                            window.navigator.mediaDevices &&
                            'getDisplayMedia' in window.navigator.mediaDevices
                        ) {
                            return
                        }
                        if (!window.navigator.mediaDevices) {
                            return
                        }
                        // getSourceId is a function that returns a promise resolving with
                        // the sourceId of the screen/window/tab to be shared.
                        if (typeof getSourceId !== 'function') {
                            console.error('shimGetDisplayMedia: getSourceId argument is not ' + 'a function')
                            return
                        }
                        window.navigator.mediaDevices.getDisplayMedia = function getDisplayMedia(constraints) {
                            return getSourceId(constraints).then(function (sourceId) {
                                var widthSpecified = constraints.video && constraints.video.width
                                var heightSpecified = constraints.video && constraints.video.height
                                var frameRateSpecified = constraints.video && constraints.video.frameRate
                                constraints.video = {
                                    mandatory: {
                                        chromeMediaSource: 'desktop',
                                        chromeMediaSourceId: sourceId,
                                        maxFrameRate: frameRateSpecified || 3
                                    }
                                }
                                if (widthSpecified) {
                                    constraints.video.mandatory.maxWidth = widthSpecified
                                }
                                if (heightSpecified) {
                                    constraints.video.mandatory.maxHeight = heightSpecified
                                }
                                return window.navigator.mediaDevices.getUserMedia(constraints)
                            })
                        }
                    }
                },
                {}
            ],
            5: [
                function (require, module, exports) {
                    /*
                     *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
                     *
                     *  Use of this source code is governed by a BSD-style license
                     *  that can be found in the LICENSE file in the root of the source
                     *  tree.
                     */
                    /* eslint-env node */
                    'use strict'

                    Object.defineProperty(exports, '__esModule', {
                        value: true
                    })

                    var _typeof =
                        typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol'
                            ? function (obj) {
                                return typeof obj
                            }
                            : function (obj) {
                                return obj &&
                                    typeof Symbol === 'function' &&
                                    obj.constructor === Symbol &&
                                    obj !== Symbol.prototype
                                    ? 'symbol'
                                    : typeof obj
                            }

                    exports.shimGetUserMedia = shimGetUserMedia

                    var _utils = require('../utils.js')

                    var utils = _interopRequireWildcard(_utils)

                    function _interopRequireWildcard(obj) {
                        if (obj && obj.__esModule) {
                            return obj
                        } else {
                            var newObj = {}
                            if (obj != null) {
                                for (var key in obj) {
                                    if (Object.prototype.hasOwnProperty.call(obj, key)) {
                                        newObj[key] = obj[key]
                                    }
                                }
                            }
                            newObj.default = obj
                            return newObj
                        }
                    }

                    var logging = utils.log

                    function shimGetUserMedia(window, browserDetails) {
                        var navigator = window && window.navigator

                        if (!navigator.mediaDevices) {
                            return
                        }

                        var constraintsToChrome_ = function constraintsToChrome_(c) {
                            if (
                                (typeof c === 'undefined' ? 'undefined' : _typeof(c)) !== 'object' ||
                                c.mandatory ||
                                c.optional
                            ) {
                                return c
                            }
                            var cc = {}
                            Object.keys(c).forEach(function (key) {
                                if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
                                    return
                                }
                                var r = _typeof(c[key]) === 'object' ? c[key] : { ideal: c[key] }
                                if (r.exact !== undefined && typeof r.exact === 'number') {
                                    r.min = r.max = r.exact
                                }
                                var oldname_ = function oldname_(prefix, name) {
                                    if (prefix) {
                                        return prefix + name.charAt(0).toUpperCase() + name.slice(1)
                                    }
                                    return name === 'deviceId' ? 'sourceId' : name
                                }
                                if (r.ideal !== undefined) {
                                    cc.optional = cc.optional || []
                                    var oc = {}
                                    if (typeof r.ideal === 'number') {
                                        oc[oldname_('min', key)] = r.ideal
                                        cc.optional.push(oc)
                                        oc = {}
                                        oc[oldname_('max', key)] = r.ideal
                                        cc.optional.push(oc)
                                    } else {
                                        oc[oldname_('', key)] = r.ideal
                                        cc.optional.push(oc)
                                    }
                                }
                                if (r.exact !== undefined && typeof r.exact !== 'number') {
                                    cc.mandatory = cc.mandatory || {}
                                    cc.mandatory[oldname_('', key)] = r.exact
                                } else {
                                    ;['min', 'max'].forEach(function (mix) {
                                        if (r[mix] !== undefined) {
                                            cc.mandatory = cc.mandatory || {}
                                            cc.mandatory[oldname_(mix, key)] = r[mix]
                                        }
                                    })
                                }
                            })
                            if (c.advanced) {
                                cc.optional = (cc.optional || []).concat(c.advanced)
                            }
                            return cc
                        }

                        var shimConstraints_ = function shimConstraints_(constraints, func) {
                            if (browserDetails.version >= 61) {
                                return func(constraints)
                            }
                            constraints = JSON.parse(JSON.stringify(constraints))
                            if (constraints && _typeof(constraints.audio) === 'object') {
                                var remap = function remap(obj, a, b) {
                                    if (a in obj && !(b in obj)) {
                                        obj[b] = obj[a]
                                        delete obj[a]
                                    }
                                }
                                constraints = JSON.parse(JSON.stringify(constraints))
                                remap(constraints.audio, 'autoGainControl', 'googAutoGainControl')
                                remap(constraints.audio, 'noiseSuppression', 'googNoiseSuppression')
                                constraints.audio = constraintsToChrome_(constraints.audio)
                            }
                            if (constraints && _typeof(constraints.video) === 'object') {
                                // Shim facingMode for mobile & surface pro.
                                var face = constraints.video.facingMode
                                face =
                                    face &&
                                    ((typeof face === 'undefined' ? 'undefined' : _typeof(face)) === 'object'
                                        ? face
                                        : { ideal: face })
                                var getSupportedFacingModeLies = browserDetails.version < 66

                                if (
                                    face &&
                                    (face.exact === 'user' ||
                                        face.exact === 'environment' ||
                                        face.ideal === 'user' ||
                                        face.ideal === 'environment') &&
                                    !(
                                        navigator.mediaDevices.getSupportedConstraints &&
                                        navigator.mediaDevices.getSupportedConstraints().facingMode &&
                                        !getSupportedFacingModeLies
                                    )
                                ) {
                                    delete constraints.video.facingMode
                                    var matches = void 0
                                    if (face.exact === 'environment' || face.ideal === 'environment') {
                                        matches = ['back', 'rear']
                                    } else if (face.exact === 'user' || face.ideal === 'user') {
                                        matches = ['front']
                                    }
                                    if (matches) {
                                        // Look for matches in label, or use last cam for back (typical).
                                        return navigator.mediaDevices.enumerateDevices().then(function (devices) {
                                            devices = devices.filter(function (d) {
                                                return d.kind === 'videoinput'
                                            })
                                            var dev = devices.find(function (d) {
                                                return matches.some(function (match) {
                                                    return d.label.toLowerCase().includes(match)
                                                })
                                            })
                                            if (!dev && devices.length && matches.includes('back')) {
                                                dev = devices[devices.length - 1] // more likely the back cam
                                            }
                                            if (dev) {
                                                constraints.video.deviceId = face.exact
                                                    ? { exact: dev.deviceId }
                                                    : { ideal: dev.deviceId }
                                            }
                                            constraints.video = constraintsToChrome_(constraints.video)
                                            logging('chrome: ' + JSON.stringify(constraints))
                                            return func(constraints)
                                        })
                                    }
                                }
                                constraints.video = constraintsToChrome_(constraints.video)
                            }
                            logging('chrome: ' + JSON.stringify(constraints))
                            return func(constraints)
                        }

                        var shimError_ = function shimError_(e) {
                            if (browserDetails.version >= 64) {
                                return e
                            }
                            return {
                                name:
                                    {
                                        PermissionDeniedError: 'NotAllowedError',
                                        PermissionDismissedError: 'NotAllowedError',
                                        InvalidStateError: 'NotAllowedError',
                                        DevicesNotFoundError: 'NotFoundError',
                                        ConstraintNotSatisfiedError: 'OverconstrainedError',
                                        TrackStartError: 'NotReadableError',
                                        MediaDeviceFailedDueToShutdown: 'NotAllowedError',
                                        MediaDeviceKillSwitchOn: 'NotAllowedError',
                                        TabCaptureError: 'AbortError',
                                        ScreenCaptureError: 'AbortError',
                                        DeviceCaptureError: 'AbortError'
                                    }[e.name] || e.name,
                                message: e.message,
                                constraint: e.constraint || e.constraintName,
                                toString: function toString() {
                                    return this.name + (this.message && ': ') + this.message
                                }
                            }
                        }

                        var getUserMedia_ = function getUserMedia_(constraints, onSuccess, onError) {
                            shimConstraints_(constraints, function (c) {
                                navigator.webkitGetUserMedia(c, onSuccess, function (e) {
                                    if (onError) {
                                        onError(shimError_(e))
                                    }
                                })
                            })
                        }
                        navigator.getUserMedia = getUserMedia_.bind(navigator)

                        // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia
                        // function which returns a Promise, it does not accept spec-style
                        // constraints.
                        if (navigator.mediaDevices.getUserMedia) {
                            var origGetUserMedia = navigator.mediaDevices.getUserMedia.bind(
                                navigator.mediaDevices
                            )
                            navigator.mediaDevices.getUserMedia = function (cs) {
                                return shimConstraints_(cs, function (c) {
                                    return origGetUserMedia(c).then(
                                        function (stream) {
                                            if (
                                                (c.audio && !stream.getAudioTracks().length) ||
                                                (c.video && !stream.getVideoTracks().length)
                                            ) {
                                                stream.getTracks().forEach(function (track) {
                                                    track.stop()
                                                })
                                                throw new DOMException('', 'NotFoundError')
                                            }
                                            return stream
                                        },
                                        function (e) {
                                            return Promise.reject(shimError_(e))
                                        }
                                    )
                                })
                            }
                        }
                    }
                },
                { '../utils.js': 11 }
            ],
            6: [
                function (require, module, exports) {
                    /*
                     *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
                     *
                     *  Use of this source code is governed by a BSD-style license
                     *  that can be found in the LICENSE file in the root of the source
                     *  tree.
                     */
                    /* eslint-env node */
                    'use strict'

                    Object.defineProperty(exports, '__esModule', {
                        value: true
                    })

                    var _typeof =
                        typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol'
                            ? function (obj) {
                                return typeof obj
                            }
                            : function (obj) {
                                return obj &&
                                    typeof Symbol === 'function' &&
                                    obj.constructor === Symbol &&
                                    obj !== Symbol.prototype
                                    ? 'symbol'
                                    : typeof obj
                            }

                    exports.shimRTCIceCandidate = shimRTCIceCandidate
                    exports.shimRTCIceCandidateRelayProtocol = shimRTCIceCandidateRelayProtocol
                    exports.shimMaxMessageSize = shimMaxMessageSize
                    exports.shimSendThrowTypeError = shimSendThrowTypeError
                    exports.shimConnectionState = shimConnectionState
                    exports.removeExtmapAllowMixed = removeExtmapAllowMixed
                    exports.shimAddIceCandidateNullOrEmpty = shimAddIceCandidateNullOrEmpty
                    exports.shimParameterlessSetLocalDescription = shimParameterlessSetLocalDescription

                    var _sdp = require('sdp')

                    var _sdp2 = _interopRequireDefault(_sdp)

                    var _utils = require('./utils')

                    var utils = _interopRequireWildcard(_utils)

                    function _interopRequireWildcard(obj) {
                        if (obj && obj.__esModule) {
                            return obj
                        } else {
                            var newObj = {}
                            if (obj != null) {
                                for (var key in obj) {
                                    if (Object.prototype.hasOwnProperty.call(obj, key)) {
                                        newObj[key] = obj[key]
                                    }
                                }
                            }
                            newObj.default = obj
                            return newObj
                        }
                    }

                    function _interopRequireDefault(obj) {
                        return obj && obj.__esModule ? obj : { default: obj }
                    }

                    function shimRTCIceCandidate(window) {
                        // foundation is arbitrarily chosen as an indicator for full support for
                        // https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface
                        if (
                            !window.RTCIceCandidate ||
                            (window.RTCIceCandidate && 'foundation' in window.RTCIceCandidate.prototype)
                        ) {
                            return
                        }

                        var NativeRTCIceCandidate = window.RTCIceCandidate
                        window.RTCIceCandidate = function RTCIceCandidate(args) {
                            // Remove the a= which shouldn't be part of the candidate string.
                            if (
                                (typeof args === 'undefined' ? 'undefined' : _typeof(args)) === 'object' &&
                                args.candidate &&
                                args.candidate.indexOf('a=') === 0
                            ) {
                                args = JSON.parse(JSON.stringify(args))
                                args.candidate = args.candidate.substr(2)
                            }

                            if (args.candidate && args.candidate.length) {
                                // Augment the native candidate with the parsed fields.
                                var nativeCandidate = new NativeRTCIceCandidate(args)
                                var parsedCandidate = _sdp2.default.parseCandidate(args.candidate)
                                var augmentedCandidate = Object.assign(nativeCandidate, parsedCandidate)

                                // Add a serializer that does not serialize the extra attributes.
                                augmentedCandidate.toJSON = function toJSON() {
                                    return {
                                        candidate: augmentedCandidate.candidate,
                                        sdpMid: augmentedCandidate.sdpMid,
                                        sdpMLineIndex: augmentedCandidate.sdpMLineIndex,
                                        usernameFragment: augmentedCandidate.usernameFragment
                                    }
                                }
                                return augmentedCandidate
                            }
                            return new NativeRTCIceCandidate(args)
                        }
                        window.RTCIceCandidate.prototype = NativeRTCIceCandidate.prototype

                        // Hook up the augmented candidate in onicecandidate and
                        // addEventListener('icecandidate', ...)
                        utils.wrapPeerConnectionEvent(window, 'icecandidate', function (e) {
                            if (e.candidate) {
                                Object.defineProperty(e, 'candidate', {
                                    value: new window.RTCIceCandidate(e.candidate),
                                    writable: 'false'
                                })
                            }
                            return e
                        })
                    }

                    function shimRTCIceCandidateRelayProtocol(window) {
                        if (
                            !window.RTCIceCandidate ||
                            (window.RTCIceCandidate && 'relayProtocol' in window.RTCIceCandidate.prototype)
                        ) {
                            return
                        }

                        // Hook up the augmented candidate in onicecandidate and
                        // addEventListener('icecandidate', ...)
                        utils.wrapPeerConnectionEvent(window, 'icecandidate', function (e) {
                            if (e.candidate) {
                                var parsedCandidate = _sdp2.default.parseCandidate(e.candidate.candidate)
                                if (parsedCandidate.type === 'relay') {
                                    // This is a libwebrtc-specific mapping of local type preference
                                    // to relayProtocol.
                                    e.candidate.relayProtocol = {
                                        0: 'tls',
                                        1: 'tcp',
                                        2: 'udp'
                                    }[parsedCandidate.priority >> 24]
                                }
                            }
                            return e
                        })
                    }

                    function shimMaxMessageSize(window, browserDetails) {
                        if (!window.RTCPeerConnection) {
                            return
                        }

                        if (!('sctp' in window.RTCPeerConnection.prototype)) {
                            Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', {
                                get: function get() {
                                    return typeof this._sctp === 'undefined' ? null : this._sctp
                                }
                            })
                        }

                        var sctpInDescription = function sctpInDescription(description) {
                            if (!description || !description.sdp) {
                                return false
                            }
                            var sections = _sdp2.default.splitSections(description.sdp)
                            sections.shift()
                            return sections.some(function (mediaSection) {
                                var mLine = _sdp2.default.parseMLine(mediaSection)
                                return (
                                    mLine && mLine.kind === 'application' && mLine.protocol.indexOf('SCTP') !== -1
                                )
                            })
                        }

                        var getRemoteFirefoxVersion = function getRemoteFirefoxVersion(description) {
                            // TODO: Is there a better solution for detecting Firefox?
                            var match = description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/)
                            if (match === null || match.length < 2) {
                                return -1
                            }
                            var version = parseInt(match[1], 10)
                            // Test for NaN (yes, this is ugly)
                            return version !== version ? -1 : version
                        }

                        var getCanSendMaxMessageSize = function getCanSendMaxMessageSize(remoteIsFirefox) {
                            // Every implementation we know can send at least 64 KiB.
                            // Note: Although Chrome is technically able to send up to 256 KiB, the
                            //       data does not reach the other peer reliably.
                            //       See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419
                            var canSendMaxMessageSize = 65536
                            if (browserDetails.browser === 'firefox') {
                                if (browserDetails.version < 57) {
                                    if (remoteIsFirefox === -1) {
                                        // FF < 57 will send in 16 KiB chunks using the deprecated PPID
                                        // fragmentation.
                                        canSendMaxMessageSize = 16384
                                    } else {
                                        // However, other FF (and RAWRTC) can reassemble PPID-fragmented
                                        // messages. Thus, supporting ~2 GiB when sending.
                                        canSendMaxMessageSize = 2147483637
                                    }
                                } else if (browserDetails.version < 60) {
                                    // Currently, all FF >= 57 will reset the remote maximum message size
                                    // to the default value when a data channel is created at a later
                                    // stage. :(
                                    // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
                                    canSendMaxMessageSize = browserDetails.version === 57 ? 65535 : 65536
                                } else {
                                    // FF >= 60 supports sending ~2 GiB
                                    canSendMaxMessageSize = 2147483637
                                }
                            }
                            return canSendMaxMessageSize
                        }

                        var getMaxMessageSize = function getMaxMessageSize(description, remoteIsFirefox) {
                            // Note: 65536 bytes is the default value from the SDP spec. Also,
                            //       every implementation we know supports receiving 65536 bytes.
                            var maxMessageSize = 65536

                            // FF 57 has a slightly incorrect default remote max message size, so
                            // we need to adjust it here to avoid a failure when sending.
                            // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697
                            if (browserDetails.browser === 'firefox' && browserDetails.version === 57) {
                                maxMessageSize = 65535
                            }

                            var match = _sdp2.default.matchPrefix(description.sdp, 'a=max-message-size:')
                            if (match.length > 0) {
                                maxMessageSize = parseInt(match[0].substr(19), 10)
                            } else if (browserDetails.browser === 'firefox' && remoteIsFirefox !== -1) {
                                // If the maximum message size is not present in the remote SDP and
                                // both local and remote are Firefox, the remote peer can receive
                                // ~2 GiB.
                                maxMessageSize = 2147483637
                            }
                            return maxMessageSize
                        }

                        var origSetRemoteDescription = window.RTCPeerConnection.prototype.setRemoteDescription
                        window.RTCPeerConnection.prototype.setRemoteDescription =
                            function setRemoteDescription() {
                                this._sctp = null
                                // Chrome decided to not expose .sctp in plan-b mode.
                                // As usual, adapter.js has to do an 'ugly worakaround'
                                // to cover up the mess.
                                if (browserDetails.browser === 'chrome' && browserDetails.version >= 76) {
                                    var _getConfiguration = this.getConfiguration(),
                                        sdpSemantics = _getConfiguration.sdpSemantics

                                    if (sdpSemantics === 'plan-b') {
                                        Object.defineProperty(this, 'sctp', {
                                            get: function get() {
                                                return typeof this._sctp === 'undefined' ? null : this._sctp
                                            },

                                            enumerable: true,
                                            configurable: true
                                        })
                                    }
                                }

                                if (sctpInDescription(arguments[0])) {
                                    // Check if the remote is FF.
                                    var isFirefox = getRemoteFirefoxVersion(arguments[0])

                                    // Get the maximum message size the local peer is capable of sending
                                    var canSendMMS = getCanSendMaxMessageSize(isFirefox)

                                    // Get the maximum message size of the remote peer.
                                    var remoteMMS = getMaxMessageSize(arguments[0], isFirefox)

                                    // Determine final maximum message size
                                    var maxMessageSize = void 0
                                    if (canSendMMS === 0 && remoteMMS === 0) {
                                        maxMessageSize = Number.POSITIVE_INFINITY
                                    } else if (canSendMMS === 0 || remoteMMS === 0) {
                                        maxMessageSize = Math.max(canSendMMS, remoteMMS)
                                    } else {
                                        maxMessageSize = Math.min(canSendMMS, remoteMMS)
                                    }

                                    // Create a dummy RTCSctpTransport object and the 'maxMessageSize'
                                    // attribute.
                                    var sctp = {}
                                    Object.defineProperty(sctp, 'maxMessageSize', {
                                        get: function get() {
                                            return maxMessageSize
                                        }
                                    })
                                    this._sctp = sctp
                                }

                                return origSetRemoteDescription.apply(this, arguments)
                            }
                    }

                    function shimSendThrowTypeError(window) {
                        if (
                            !(
                                window.RTCPeerConnection &&
                                'createDataChannel' in window.RTCPeerConnection.prototype
                            )
                        ) {
                            return
                        }

                        // Note: Although Firefox >= 57 has a native implementation, the maximum
                        //       message size can be reset for all data channels at a later stage.
                        //       See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831

                        function wrapDcSend(dc, pc) {
                            var origDataChannelSend = dc.send
                            dc.send = function send() {
                                var data = arguments[0]
                                var length = data.length || data.size || data.byteLength
                                if (dc.readyState === 'open' && pc.sctp && length > pc.sctp.maxMessageSize) {
                                    throw new TypeError(
                                        'Message too large (can send a maximum of ' + pc.sctp.maxMessageSize + ' bytes)'
                                    )
                                }
                                return origDataChannelSend.apply(dc, arguments)
                            }
                        }
                        var origCreateDataChannel = window.RTCPeerConnection.prototype.createDataChannel
                        window.RTCPeerConnection.prototype.createDataChannel = function createDataChannel() {
                            var dataChannel = origCreateDataChannel.apply(this, arguments)
                            wrapDcSend(dataChannel, this)
                            return dataChannel
                        }
                        utils.wrapPeerConnectionEvent(window, 'datachannel', function (e) {
                            wrapDcSend(e.channel, e.target)
                            return e
                        })
                    }

                    /* shims RTCConnectionState by pretending it is the same as iceConnectionState.
                     * See https://bugs.chromium.org/p/webrtc/issues/detail?id=6145#c12
                     * for why this is a valid hack in Chrome. In Firefox it is slightly incorrect
                     * since DTLS failures would be hidden. See
                     * https://bugzilla.mozilla.org/show_bug.cgi?id=1265827
                     * for the Firefox tracking bug.
                     */
                    function shimConnectionState(window) {
                        if (
                            !window.RTCPeerConnection ||
                            'connectionState' in window.RTCPeerConnection.prototype
                        ) {
                            return
                        }
                        var proto = window.RTCPeerConnection.prototype
                        Object.defineProperty(proto, 'connectionState', {
                            get: function get() {
                                return (
                                    {
                                        completed: 'connected',
                                        checking: 'connecting'
                                    }[this.iceConnectionState] || this.iceConnectionState
                                )
                            },

                            enumerable: true,
                            configurable: true
                        })
                        Object.defineProperty(proto, 'onconnectionstatechange', {
                            get: function get() {
                                return this._onconnectionstatechange || null
                            },
                            set: function set(cb) {
                                if (this._onconnectionstatechange) {
                                    this.removeEventListener('connectionstatechange', this._onconnectionstatechange)
                                    delete this._onconnectionstatechange
                                }
                                if (cb) {
                                    this.addEventListener(
                                        'connectionstatechange',
                                        (this._onconnectionstatechange = cb)
                                    )
                                }
                            },

                            enumerable: true,
                            configurable: true
                        })
                            ;['setLocalDescription', 'setRemoteDescription'].forEach(function (method) {
                                var origMethod = proto[method]
                                proto[method] = function () {
                                    if (!this._connectionstatechangepoly) {
                                        this._connectionstatechangepoly = function (e) {
                                            var pc = e.target
                                            if (pc._lastConnectionState !== pc.connectionState) {
                                                pc._lastConnectionState = pc.connectionState
                                                var newEvent = new Event('connectionstatechange', e)
                                                pc.dispatchEvent(newEvent)
                                            }
                                            return e
                                        }
                                        this.addEventListener('iceconnectionstatechange', this._connectionstatechangepoly)
                                    }
                                    return origMethod.apply(this, arguments)
                                }
                            })
                    }

                    function removeExtmapAllowMixed(window, browserDetails) {
                        /* remove a=extmap-allow-mixed for webrtc.org < M71 */
                        if (!window.RTCPeerConnection) {
                            return
                        }
                        if (browserDetails.browser === 'chrome' && browserDetails.version >= 71) {
                            return
                        }
                        if (browserDetails.browser === 'safari' && browserDetails.version >= 605) {
                            return
                        }
                        var nativeSRD = window.RTCPeerConnection.prototype.setRemoteDescription
                        window.RTCPeerConnection.prototype.setRemoteDescription = function setRemoteDescription(
                            desc
                        ) {
                            if (desc && desc.sdp && desc.sdp.indexOf('\na=extmap-allow-mixed') !== -1) {
                                var sdp = desc.sdp
                                    .split('\n')
                                    .filter(function (line) {
                                        return line.trim() !== 'a=extmap-allow-mixed'
                                    })
                                    .join('\n')
                                // Safari enforces read-only-ness of RTCSessionDescription fields.
                                if (window.RTCSessionDescription && desc instanceof window.RTCSessionDescription) {
                                    arguments[0] = new window.RTCSessionDescription({
                                        type: desc.type,
                                        sdp: sdp
                                    })
                                } else {
                                    desc.sdp = sdp
                                }
                            }
                            return nativeSRD.apply(this, arguments)
                        }
                    }

                    function shimAddIceCandidateNullOrEmpty(window, browserDetails) {
                        // Support for addIceCandidate(null or undefined)
                        // as well as addIceCandidate({candidate: "", ...})
                        // https://bugs.chromium.org/p/chromium/issues/detail?id=978582
                        // Note: must be called before other polyfills which change the signature.
                        if (!(window.RTCPeerConnection && window.RTCPeerConnection.prototype)) {
                            return
                        }
                        var nativeAddIceCandidate = window.RTCPeerConnection.prototype.addIceCandidate
                        if (!nativeAddIceCandidate || nativeAddIceCandidate.length === 0) {
                            return
                        }
                        window.RTCPeerConnection.prototype.addIceCandidate = function addIceCandidate() {
                            if (!arguments[0]) {
                                if (arguments[1]) {
                                    arguments[1].apply(null)
                                }
                                return Promise.resolve()
                            }
                            // Firefox 68+ emits and processes {candidate: "", ...}, ignore
                            // in older versions.
                            // Native support for ignoring exists for Chrome M77+.
                            // Safari ignores as well, exact version unknown but works in the same
                            // version that also ignores addIceCandidate(null).
                            if (
                                ((browserDetails.browser === 'chrome' && browserDetails.version < 78) ||
                                    (browserDetails.browser === 'firefox' && browserDetails.version < 68) ||
                                    browserDetails.browser === 'safari') &&
                                arguments[0] &&
                                arguments[0].candidate === ''
                            ) {
                                return Promise.resolve()
                            }
                            return nativeAddIceCandidate.apply(this, arguments)
                        }
                    }

                    // Note: Make sure to call this ahead of APIs that modify
                    // setLocalDescription.length
                    function shimParameterlessSetLocalDescription(window, browserDetails) {
                        if (!(window.RTCPeerConnection && window.RTCPeerConnection.prototype)) {
                            return
                        }
                        var nativeSetLocalDescription = window.RTCPeerConnection.prototype.setLocalDescription
                        if (!nativeSetLocalDescription || nativeSetLocalDescription.length === 0) {
                            return
                        }
                        window.RTCPeerConnection.prototype.setLocalDescription =
                            function setLocalDescription() {
                                var _this = this

                                var desc = arguments[0] || {}
                                if (
                                    (typeof desc === 'undefined' ? 'undefined' : _typeof(desc)) !== 'object' ||
                                    (desc.type && desc.sdp)
                                ) {
                                    return nativeSetLocalDescription.apply(this, arguments)
                                }
                                // The remaining steps should technically happen when SLD comes off the
                                // RTCPeerConnection's operations chain (not ahead of going on it), but
                                // this is too difficult to shim. Instead, this shim only covers the
                                // common case where the operations chain is empty. This is imperfect, but
                                // should cover many cases. Rationale: Even if we can't reduce the glare
                                // window to zero on imperfect implementations, there's value in tapping
                                // into the perfect negotiation pattern that several browsers support.
                                desc = { type: desc.type, sdp: desc.sdp }
                                if (!desc.type) {
                                    switch (this.signalingState) {
                                        case 'stable':
                                        case 'have-local-offer':
                                        case 'have-remote-pranswer':
                                            desc.type = 'offer'
                                            break
                                        default:
                                            desc.type = 'answer'
                                            break
                                    }
                                }
                                if (desc.sdp || (desc.type !== 'offer' && desc.type !== 'answer')) {
                                    return nativeSetLocalDescription.apply(this, [desc])
                                }
                                var func = desc.type === 'offer' ? this.createOffer : this.createAnswer
                                return func.apply(this).then(function (d) {
                                    return nativeSetLocalDescription.apply(_this, [d])
                                })
                            }
                    }
                },
                { './utils': 11, sdp: 12 }
            ],
            7: [
                function (require, module, exports) {
                    /*
                     *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
                     *
                     *  Use of this source code is governed by a BSD-style license
                     *  that can be found in the LICENSE file in the root of the source
                     *  tree.
                     */
                    /* eslint-env node */
                    'use strict'

                    Object.defineProperty(exports, '__esModule', {
                        value: true
                    })
                    exports.shimGetDisplayMedia = exports.shimGetUserMedia = undefined

                    var _typeof =
                        typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol'
                            ? function (obj) {
                                return typeof obj
                            }
                            : function (obj) {
                                return obj &&
                                    typeof Symbol === 'function' &&
                                    obj.constructor === Symbol &&
                                    obj !== Symbol.prototype
                                    ? 'symbol'
                                    : typeof obj
                            }

                    var _getusermedia = require('./getusermedia')

                    Object.defineProperty(exports, 'shimGetUserMedia', {
                        enumerable: true,
                        get: function get() {
                            return _getusermedia.shimGetUserMedia
                        }
                    })

                    var _getdisplaymedia = require('./getdisplaymedia')

                    Object.defineProperty(exports, 'shimGetDisplayMedia', {
                        enumerable: true,
                        get: function get() {
                            return _getdisplaymedia.shimGetDisplayMedia
                        }
                    })
                    exports.shimOnTrack = shimOnTrack
                    exports.shimPeerConnection = shimPeerConnection
                    exports.shimSenderGetStats = shimSenderGetStats
                    exports.shimReceiverGetStats = shimReceiverGetStats
                    exports.shimRemoveStream = shimRemoveStream
                    exports.shimRTCDataChannel = shimRTCDataChannel
                    exports.shimAddTransceiver = shimAddTransceiver
                    exports.shimGetParameters = shimGetParameters
                    exports.shimCreateOffer = shimCreateOffer
                    exports.shimCreateAnswer = shimCreateAnswer

                    var _utils = require('../utils')

                    var utils = _interopRequireWildcard(_utils)

                    function _interopRequireWildcard(obj) {
                        if (obj && obj.__esModule) {
                            return obj
                        } else {
                            var newObj = {}
                            if (obj != null) {
                                for (var key in obj) {
                                    if (Object.prototype.hasOwnProperty.call(obj, key)) {
                                        newObj[key] = obj[key]
                                    }
                                }
                            }
                            newObj.default = obj
                            return newObj
                        }
                    }

                    function _toConsumableArray(arr) {
                        if (Array.isArray(arr)) {
                            for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
                                arr2[i] = arr[i]
                            }
                            return arr2
                        } else {
                            return Array.from(arr)
                        }
                    }

                    function _defineProperty(obj, key, value) {
                        if (key in obj) {
                            Object.defineProperty(obj, key, {
                                value: value,
                                enumerable: true,
                                configurable: true,
                                writable: true
                            })
                        } else {
                            obj[key] = value
                        }
                        return obj
                    }

                    function shimOnTrack(window) {
                        if (
                            (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' &&
                            window.RTCTrackEvent &&
                            'receiver' in window.RTCTrackEvent.prototype &&
                            !('transceiver' in window.RTCTrackEvent.prototype)
                        ) {
                            Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {
                                get: function get() {
                                    return { receiver: this.receiver }
                                }
                            })
                        }
                    }

                    function shimPeerConnection(window, browserDetails) {
                        if (
                            (typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== 'object' ||
                            !(window.RTCPeerConnection || window.mozRTCPeerConnection)
                        ) {
                            return // probably media.peerconnection.enabled=false in about:config
                        }
                        if (!window.RTCPeerConnection && window.mozRTCPeerConnection) {
                            // very basic support for old versions.
                            window.RTCPeerConnection = window.mozRTCPeerConnection
                        }

                        if (browserDetails.version < 53) {
                            // shim away need for obsolete RTCIceCandidate/RTCSessionDescription.
                            ;['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'].forEach(function (
                                method
                            ) {
                                var nativeMethod = window.RTCPeerConnection.prototype[method]
                                var methodObj = _defineProperty({}, method, function () {
                                    arguments[0] = new (
                                        method === 'addIceCandidate'
                                            ? window.RTCIceCandidate
                                            : window.RTCSessionDescription
                                    )(arguments[0])
                                    return nativeMethod.apply(this, arguments)
                                })
                                window.RTCPeerConnection.prototype[method] = methodObj[method]
                            })
                        }

                        var modernStatsTypes = {
                            inboundrtp: 'inbound-rtp',
                            outboundrtp: 'outbound-rtp',
                            candidatepair: 'candidate-pair',
                            localcandidate: 'local-candidate',
                            remotecandidate: 'remote-candidate'
                        }

                        var nativeGetStats = window.RTCPeerConnection.prototype.getStats
                        window.RTCPeerConnection.prototype.getStats = function getStats() {
                            var _arguments = Array.prototype.slice.call(arguments),
                                selector = _arguments[0],
                                onSucc = _arguments[1],
                                onErr = _arguments[2]

                            return nativeGetStats
                                .apply(this, [selector || null])
                                .then(function (stats) {
                                    if (browserDetails.version < 53 && !onSucc) {
                                        // Shim only promise getStats with spec-hyphens in type names
                                        // Leave callback version alone; misc old uses of forEach before Map
                                        try {
                                            stats.forEach(function (stat) {
                                                stat.type = modernStatsTypes[stat.type] || stat.type
                                            })
                                        } catch (e) {
                                            if (e.name !== 'TypeError') {
                                                throw e
                                            }
                                            // Avoid TypeError: "type" is read-only, in old versions. 34-43ish
                                            stats.forEach(function (stat, i) {
                                                stats.set(
                                                    i,
                                                    Object.assign({}, stat, {
                                                        type: modernStatsTypes[stat.type] || stat.type
                                                    })
                                                )
                                            })
                                        }
                                    }
                                    return stats
                                })
                                .then(onSucc, onErr)
                        }
                    }

                    function shimSenderGetStats(window) {
                        if (
                            !(
                                (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' &&
                                window.RTCPeerConnection &&
                                window.RTCRtpSender
                            )
                        ) {
                            return
                        }
                        if (window.RTCRtpSender && 'getStats' in window.RTCRtpSender.prototype) {
                            return
                        }
                        var origGetSenders = window.RTCPeerConnection.prototype.getSenders
                        if (origGetSenders) {
                            window.RTCPeerConnection.prototype.getSenders = function getSenders() {
                                var _this = this

                                var senders = origGetSenders.apply(this, [])
                                senders.forEach(function (sender) {
                                    return (sender._pc = _this)
                                })
                                return senders
                            }
                        }

                        var origAddTrack = window.RTCPeerConnection.prototype.addTrack
                        if (origAddTrack) {
                            window.RTCPeerConnection.prototype.addTrack = function addTrack() {
                                var sender = origAddTrack.apply(this, arguments)
                                sender._pc = this
                                return sender
                            }
                        }
                        window.RTCRtpSender.prototype.getStats = function getStats() {
                            return this.track ? this._pc.getStats(this.track) : Promise.resolve(new Map())
                        }
                    }

                    function shimReceiverGetStats(window) {
                        if (
                            !(
                                (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' &&
                                window.RTCPeerConnection &&
                                window.RTCRtpSender
                            )
                        ) {
                            return
                        }
                        if (window.RTCRtpSender && 'getStats' in window.RTCRtpReceiver.prototype) {
                            return
                        }
                        var origGetReceivers = window.RTCPeerConnection.prototype.getReceivers
                        if (origGetReceivers) {
                            window.RTCPeerConnection.prototype.getReceivers = function getReceivers() {
                                var _this2 = this

                                var receivers = origGetReceivers.apply(this, [])
                                receivers.forEach(function (receiver) {
                                    return (receiver._pc = _this2)
                                })
                                return receivers
                            }
                        }
                        utils.wrapPeerConnectionEvent(window, 'track', function (e) {
                            e.receiver._pc = e.srcElement
                            return e
                        })
                        window.RTCRtpReceiver.prototype.getStats = function getStats() {
                            return this._pc.getStats(this.track)
                        }
                    }

                    function shimRemoveStream(window) {
                        if (!window.RTCPeerConnection || 'removeStream' in window.RTCPeerConnection.prototype) {
                            return
                        }
                        window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) {
                            var _this3 = this

                            utils.deprecated('removeStream', 'removeTrack')
                            this.getSenders().forEach(function (sender) {
                                if (sender.track && stream.getTracks().includes(sender.track)) {
                                    _this3.removeTrack(sender)
                                }
                            })
                        }
                    }

                    function shimRTCDataChannel(window) {
                        // rename DataChannel to RTCDataChannel (native fix in FF60):
                        // https://bugzilla.mozilla.org/show_bug.cgi?id=1173851
                        if (window.DataChannel && !window.RTCDataChannel) {
                            window.RTCDataChannel = window.DataChannel
                        }
                    }

                    function shimAddTransceiver(window) {
                        // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647
                        // Firefox ignores the init sendEncodings options passed to addTransceiver
                        // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918
                        if (
                            !(
                                (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' &&
                                window.RTCPeerConnection
                            )
                        ) {
                            return
                        }
                        var origAddTransceiver = window.RTCPeerConnection.prototype.addTransceiver
                        if (origAddTransceiver) {
                            window.RTCPeerConnection.prototype.addTransceiver = function addTransceiver() {
                                this.setParametersPromises = []
                                // WebIDL input coercion and validation
                                var sendEncodings = arguments[1] && arguments[1].sendEncodings
                                if (sendEncodings === undefined) {
                                    sendEncodings = []
                                }
                                sendEncodings = [].concat(_toConsumableArray(sendEncodings))
                                var shouldPerformCheck = sendEncodings.length > 0
                                if (shouldPerformCheck) {
                                    // If sendEncodings params are provided, validate grammar
                                    sendEncodings.forEach(function (encodingParam) {
                                        if ('rid' in encodingParam) {
                                            var ridRegex = /^[a-z0-9]{0,16}$/i
                                            if (!ridRegex.test(encodingParam.rid)) {
                                                throw new TypeError('Invalid RID value provided.')
                                            }
                                        }
                                        if ('scaleResolutionDownBy' in encodingParam) {
                                            if (!(parseFloat(encodingParam.scaleResolutionDownBy) >= 1.0)) {
                                                throw new RangeError('scale_resolution_down_by must be >= 1.0')
                                            }
                                        }
                                        if ('maxFramerate' in encodingParam) {
                                            if (!(parseFloat(encodingParam.maxFramerate) >= 0)) {
                                                throw new RangeError('max_framerate must be >= 0.0')
                                            }
                                        }
                                    })
                                }
                                var transceiver = origAddTransceiver.apply(this, arguments)
                                if (shouldPerformCheck) {
                                    // Check if the init options were applied. If not we do this in an
                                    // asynchronous way and save the promise reference in a global object.
                                    // This is an ugly hack, but at the same time is way more robust than
                                    // checking the sender parameters before and after the createOffer
                                    // Also note that after the createoffer we are not 100% sure that
                                    // the params were asynchronously applied so we might miss the
                                    // opportunity to recreate offer.
                                    var sender = transceiver.sender

                                    var params = sender.getParameters()
                                    if (
                                        !('encodings' in params) ||
                                        // Avoid being fooled by patched getParameters() below.
                                        (params.encodings.length === 1 && Object.keys(params.encodings[0]).length === 0)
                                    ) {
                                        params.encodings = sendEncodings
                                        sender.sendEncodings = sendEncodings
                                        this.setParametersPromises.push(
                                            sender
                                                .setParameters(params)
                                                .then(function () {
                                                    delete sender.sendEncodings
                                                })
                                                .catch(function () {
                                                    delete sender.sendEncodings
                                                })
                                        )
                                    }
                                }
                                return transceiver
                            }
                        }
                    }

                    function shimGetParameters(window) {
                        if (
                            !(
                                (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' &&
                                window.RTCRtpSender
                            )
                        ) {
                            return
                        }
                        var origGetParameters = window.RTCRtpSender.prototype.getParameters
                        if (origGetParameters) {
                            window.RTCRtpSender.prototype.getParameters = function getParameters() {
                                var params = origGetParameters.apply(this, arguments)
                                if (!('encodings' in params)) {
                                    params.encodings = [].concat(this.sendEncodings || [{}])
                                }
                                return params
                            }
                        }
                    }

                    function shimCreateOffer(window) {
                        // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647
                        // Firefox ignores the init sendEncodings options passed to addTransceiver
                        // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918
                        if (
                            !(
                                (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' &&
                                window.RTCPeerConnection
                            )
                        ) {
                            return
                        }
                        var origCreateOffer = window.RTCPeerConnection.prototype.createOffer
                        window.RTCPeerConnection.prototype.createOffer = function createOffer() {
                            var _this4 = this,
                                _arguments2 = arguments

                            if (this.setParametersPromises && this.setParametersPromises.length) {
                                return Promise.all(this.setParametersPromises)
                                    .then(function () {
                                        return origCreateOffer.apply(_this4, _arguments2)
                                    })
                                    .finally(function () {
                                        _this4.setParametersPromises = []
                                    })
                            }
                            return origCreateOffer.apply(this, arguments)
                        }
                    }

                    function shimCreateAnswer(window) {
                        // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647
                        // Firefox ignores the init sendEncodings options passed to addTransceiver
                        // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918
                        if (
                            !(
                                (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' &&
                                window.RTCPeerConnection
                            )
                        ) {
                            return
                        }
                        var origCreateAnswer = window.RTCPeerConnection.prototype.createAnswer
                        window.RTCPeerConnection.prototype.createAnswer = function createAnswer() {
                            var _this5 = this,
                                _arguments3 = arguments

                            if (this.setParametersPromises && this.setParametersPromises.length) {
                                return Promise.all(this.setParametersPromises)
                                    .then(function () {
                                        return origCreateAnswer.apply(_this5, _arguments3)
                                    })
                                    .finally(function () {
                                        _this5.setParametersPromises = []
                                    })
                            }
                            return origCreateAnswer.apply(this, arguments)
                        }
                    }
                },
                { '../utils': 11, './getdisplaymedia': 8, './getusermedia': 9 }
            ],
            8: [
                function (require, module, exports) {
                    /*
                     *  Copyright (c) 2018 The adapter.js project authors. All Rights Reserved.
                     *
                     *  Use of this source code is governed by a BSD-style license
                     *  that can be found in the LICENSE file in the root of the source
                     *  tree.
                     */
                    /* eslint-env node */
                    'use strict'

                    Object.defineProperty(exports, '__esModule', {
                        value: true
                    })
                    exports.shimGetDisplayMedia = shimGetDisplayMedia
                    function shimGetDisplayMedia(window, preferredMediaSource) {
                        if (
                            window.navigator.mediaDevices &&
                            'getDisplayMedia' in window.navigator.mediaDevices
                        ) {
                            return
                        }
                        if (!window.navigator.mediaDevices) {
                            return
                        }
                        window.navigator.mediaDevices.getDisplayMedia = function getDisplayMedia(constraints) {
                            if (!(constraints && constraints.video)) {
                                var err = new DOMException(
                                    'getDisplayMedia without video ' + 'constraints is undefined'
                                )
                                err.name = 'NotFoundError'
                                // from https://heycam.github.io/webidl/#idl-DOMException-error-names
                                err.code = 8
                                return Promise.reject(err)
                            }
                            if (constraints.video === true) {
                                constraints.video = { mediaSource: preferredMediaSource }
                            } else {
                                constraints.video.mediaSource = preferredMediaSource
                            }
                            return window.navigator.mediaDevices.getUserMedia(constraints)
                        }
                    }
                },
                {}
            ],
            9: [
                function (require, module, exports) {
                    /*
                     *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
                     *
                     *  Use of this source code is governed by a BSD-style license
                     *  that can be found in the LICENSE file in the root of the source
                     *  tree.
                     */
                    /* eslint-env node */
                    'use strict'

                    Object.defineProperty(exports, '__esModule', {
                        value: true
                    })

                    var _typeof =
                        typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol'
                            ? function (obj) {
                                return typeof obj
                            }
                            : function (obj) {
                                return obj &&
                                    typeof Symbol === 'function' &&
                                    obj.constructor === Symbol &&
                                    obj !== Symbol.prototype
                                    ? 'symbol'
                                    : typeof obj
                            }

                    exports.shimGetUserMedia = shimGetUserMedia

                    var _utils = require('../utils')

                    var utils = _interopRequireWildcard(_utils)

                    function _interopRequireWildcard(obj) {
                        if (obj && obj.__esModule) {
                            return obj
                        } else {
                            var newObj = {}
                            if (obj != null) {
                                for (var key in obj) {
                                    if (Object.prototype.hasOwnProperty.call(obj, key)) {
                                        newObj[key] = obj[key]
                                    }
                                }
                            }
                            newObj.default = obj
                            return newObj
                        }
                    }

                    function shimGetUserMedia(window, browserDetails) {
                        var navigator = window && window.navigator
                        var MediaStreamTrack = window && window.MediaStreamTrack

                        navigator.getUserMedia = function (constraints, onSuccess, onError) {
                            // Replace Firefox 44+'s deprecation warning with unprefixed version.
                            utils.deprecated('navigator.getUserMedia', 'navigator.mediaDevices.getUserMedia')
                            navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError)
                        }

                        if (
                            !(
                                browserDetails.version > 55 &&
                                'autoGainControl' in navigator.mediaDevices.getSupportedConstraints()
                            )
                        ) {
                            var remap = function remap(obj, a, b) {
                                if (a in obj && !(b in obj)) {
                                    obj[b] = obj[a]
                                    delete obj[a]
                                }
                            }

                            var nativeGetUserMedia = navigator.mediaDevices.getUserMedia.bind(
                                navigator.mediaDevices
                            )
                            navigator.mediaDevices.getUserMedia = function (c) {
                                if (
                                    (typeof c === 'undefined' ? 'undefined' : _typeof(c)) === 'object' &&
                                    _typeof(c.audio) === 'object'
                                ) {
                                    c = JSON.parse(JSON.stringify(c))
                                    remap(c.audio, 'autoGainControl', 'mozAutoGainControl')
                                    remap(c.audio, 'noiseSuppression', 'mozNoiseSuppression')
                                }
                                return nativeGetUserMedia(c)
                            }

                            if (MediaStreamTrack && MediaStreamTrack.prototype.getSettings) {
                                var nativeGetSettings = MediaStreamTrack.prototype.getSettings
                                MediaStreamTrack.prototype.getSettings = function () {
                                    var obj = nativeGetSettings.apply(this, arguments)
                                    remap(obj, 'mozAutoGainControl', 'autoGainControl')
                                    remap(obj, 'mozNoiseSuppression', 'noiseSuppression')
                                    return obj
                                }
                            }

                            if (MediaStreamTrack && MediaStreamTrack.prototype.applyConstraints) {
                                var nativeApplyConstraints = MediaStreamTrack.prototype.applyConstraints
                                MediaStreamTrack.prototype.applyConstraints = function (c) {
                                    if (
                                        this.kind === 'audio' &&
                                        (typeof c === 'undefined' ? 'undefined' : _typeof(c)) === 'object'
                                    ) {
                                        c = JSON.parse(JSON.stringify(c))
                                        remap(c, 'autoGainControl', 'mozAutoGainControl')
                                        remap(c, 'noiseSuppression', 'mozNoiseSuppression')
                                    }
                                    return nativeApplyConstraints.apply(this, [c])
                                }
                            }
                        }
                    }
                },
                { '../utils': 11 }
            ],
            10: [
                function (require, module, exports) {
                    /*
                     *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
                     *
                     *  Use of this source code is governed by a BSD-style license
                     *  that can be found in the LICENSE file in the root of the source
                     *  tree.
                     */
                    'use strict'

                    Object.defineProperty(exports, '__esModule', {
                        value: true
                    })

                    var _typeof =
                        typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol'
                            ? function (obj) {
                                return typeof obj
                            }
                            : function (obj) {
                                return obj &&
                                    typeof Symbol === 'function' &&
                                    obj.constructor === Symbol &&
                                    obj !== Symbol.prototype
                                    ? 'symbol'
                                    : typeof obj
                            }

                    exports.shimLocalStreamsAPI = shimLocalStreamsAPI
                    exports.shimRemoteStreamsAPI = shimRemoteStreamsAPI
                    exports.shimCallbacksAPI = shimCallbacksAPI
                    exports.shimGetUserMedia = shimGetUserMedia
                    exports.shimConstraints = shimConstraints
                    exports.shimRTCIceServerUrls = shimRTCIceServerUrls
                    exports.shimTrackEventTransceiver = shimTrackEventTransceiver
                    exports.shimCreateOfferLegacy = shimCreateOfferLegacy
                    exports.shimAudioContext = shimAudioContext

                    var _utils = require('../utils')

                    var utils = _interopRequireWildcard(_utils)

                    function _interopRequireWildcard(obj) {
                        if (obj && obj.__esModule) {
                            return obj
                        } else {
                            var newObj = {}
                            if (obj != null) {
                                for (var key in obj) {
                                    if (Object.prototype.hasOwnProperty.call(obj, key)) {
                                        newObj[key] = obj[key]
                                    }
                                }
                            }
                            newObj.default = obj
                            return newObj
                        }
                    }

                    function shimLocalStreamsAPI(window) {
                        if (
                            (typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== 'object' ||
                            !window.RTCPeerConnection
                        ) {
                            return
                        }
                        if (!('getLocalStreams' in window.RTCPeerConnection.prototype)) {
                            window.RTCPeerConnection.prototype.getLocalStreams = function getLocalStreams() {
                                if (!this._localStreams) {
                                    this._localStreams = []
                                }
                                return this._localStreams
                            }
                        }
                        if (!('addStream' in window.RTCPeerConnection.prototype)) {
                            var _addTrack = window.RTCPeerConnection.prototype.addTrack
                            window.RTCPeerConnection.prototype.addStream = function addStream(stream) {
                                var _this = this

                                if (!this._localStreams) {
                                    this._localStreams = []
                                }
                                if (!this._localStreams.includes(stream)) {
                                    this._localStreams.push(stream)
                                }
                                // Try to emulate Chrome's behaviour of adding in audio-video order.
                                // Safari orders by track id.
                                stream.getAudioTracks().forEach(function (track) {
                                    return _addTrack.call(_this, track, stream)
                                })
                                stream.getVideoTracks().forEach(function (track) {
                                    return _addTrack.call(_this, track, stream)
                                })
                            }

                            window.RTCPeerConnection.prototype.addTrack = function addTrack(track) {
                                var _this2 = this

                                for (
                                    var _len = arguments.length, streams = Array(_len > 1 ? _len - 1 : 0), _key = 1;
                                    _key < _len;
                                    _key++
                                ) {
                                    streams[_key - 1] = arguments[_key]
                                }

                                if (streams) {
                                    streams.forEach(function (stream) {
                                        if (!_this2._localStreams) {
                                            _this2._localStreams = [stream]
                                        } else if (!_this2._localStreams.includes(stream)) {
                                            _this2._localStreams.push(stream)
                                        }
                                    })
                                }
                                return _addTrack.apply(this, arguments)
                            }
                        }
                        if (!('removeStream' in window.RTCPeerConnection.prototype)) {
                            window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) {
                                var _this3 = this

                                if (!this._localStreams) {
                                    this._localStreams = []
                                }
                                var index = this._localStreams.indexOf(stream)
                                if (index === -1) {
                                    return
                                }
                                this._localStreams.splice(index, 1)
                                var tracks = stream.getTracks()
                                this.getSenders().forEach(function (sender) {
                                    if (tracks.includes(sender.track)) {
                                        _this3.removeTrack(sender)
                                    }
                                })
                            }
                        }
                    }

                    function shimRemoteStreamsAPI(window) {
                        if (
                            (typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== 'object' ||
                            !window.RTCPeerConnection
                        ) {
                            return
                        }
                        if (!('getRemoteStreams' in window.RTCPeerConnection.prototype)) {
                            window.RTCPeerConnection.prototype.getRemoteStreams = function getRemoteStreams() {
                                return this._remoteStreams ? this._remoteStreams : []
                            }
                        }
                        if (!('onaddstream' in window.RTCPeerConnection.prototype)) {
                            Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', {
                                get: function get() {
                                    return this._onaddstream
                                },
                                set: function set(f) {
                                    var _this4 = this

                                    if (this._onaddstream) {
                                        this.removeEventListener('addstream', this._onaddstream)
                                        this.removeEventListener('track', this._onaddstreampoly)
                                    }
                                    this.addEventListener('addstream', (this._onaddstream = f))
                                    this.addEventListener(
                                        'track',
                                        (this._onaddstreampoly = function (e) {
                                            e.streams.forEach(function (stream) {
                                                if (!_this4._remoteStreams) {
                                                    _this4._remoteStreams = []
                                                }
                                                if (_this4._remoteStreams.includes(stream)) {
                                                    return
                                                }
                                                _this4._remoteStreams.push(stream)
                                                var event = new Event('addstream')
                                                event.stream = stream
                                                _this4.dispatchEvent(event)
                                            })
                                        })
                                    )
                                }
                            })
                            var origSetRemoteDescription = window.RTCPeerConnection.prototype.setRemoteDescription
                            window.RTCPeerConnection.prototype.setRemoteDescription =
                                function setRemoteDescription() {
                                    var pc = this
                                    if (!this._onaddstreampoly) {
                                        this.addEventListener(
                                            'track',
                                            (this._onaddstreampoly = function (e) {
                                                e.streams.forEach(function (stream) {
                                                    if (!pc._remoteStreams) {
                                                        pc._remoteStreams = []
                                                    }
                                                    if (pc._remoteStreams.indexOf(stream) >= 0) {
                                                        return
                                                    }
                                                    pc._remoteStreams.push(stream)
                                                    var event = new Event('addstream')
                                                    event.stream = stream
                                                    pc.dispatchEvent(event)
                                                })
                                            })
                                        )
                                    }
                                    return origSetRemoteDescription.apply(pc, arguments)
                                }
                        }
                    }

                    function shimCallbacksAPI(window) {
                        if (
                            (typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== 'object' ||
                            !window.RTCPeerConnection
                        ) {
                            return
                        }
                        var prototype = window.RTCPeerConnection.prototype
                        var origCreateOffer = prototype.createOffer
                        var origCreateAnswer = prototype.createAnswer
                        var setLocalDescription = prototype.setLocalDescription
                        var setRemoteDescription = prototype.setRemoteDescription
                        var addIceCandidate = prototype.addIceCandidate

                        prototype.createOffer = function createOffer(successCallback, failureCallback) {
                            var options = arguments.length >= 2 ? arguments[2] : arguments[0]
                            var promise = origCreateOffer.apply(this, [options])
                            if (!failureCallback) {
                                return promise
                            }
                            promise.then(successCallback, failureCallback)
                            return Promise.resolve()
                        }

                        prototype.createAnswer = function createAnswer(successCallback, failureCallback) {
                            var options = arguments.length >= 2 ? arguments[2] : arguments[0]
                            var promise = origCreateAnswer.apply(this, [options])
                            if (!failureCallback) {
                                return promise
                            }
                            promise.then(successCallback, failureCallback)
                            return Promise.resolve()
                        }

                        var withCallback = function withCallback(
                            description,
                            successCallback,
                            failureCallback
                        ) {
                            var promise = setLocalDescription.apply(this, [description])
                            if (!failureCallback) {
                                return promise
                            }
                            promise.then(successCallback, failureCallback)
                            return Promise.resolve()
                        }
                        prototype.setLocalDescription = withCallback

                        withCallback = function withCallback(description, successCallback, failureCallback) {
                            var promise = setRemoteDescription.apply(this, [description])
                            if (!failureCallback) {
                                return promise
                            }
                            promise.then(successCallback, failureCallback)
                            return Promise.resolve()
                        }
                        prototype.setRemoteDescription = withCallback

                        withCallback = function withCallback(candidate, successCallback, failureCallback) {
                            var promise = addIceCandidate.apply(this, [candidate])
                            if (!failureCallback) {
                                return promise
                            }
                            promise.then(successCallback, failureCallback)
                            return Promise.resolve()
                        }
                        prototype.addIceCandidate = withCallback
                    }

                    function shimGetUserMedia(window) {
                        var navigator = window && window.navigator

                        if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
                            // shim not needed in Safari 12.1
                            var mediaDevices = navigator.mediaDevices
                            var _getUserMedia = mediaDevices.getUserMedia.bind(mediaDevices)
                            navigator.mediaDevices.getUserMedia = function (constraints) {
                                return _getUserMedia(shimConstraints(constraints))
                            }
                        }

                        if (
                            !navigator.getUserMedia &&
                            navigator.mediaDevices &&
                            navigator.mediaDevices.getUserMedia
                        ) {
                            navigator.getUserMedia = function getUserMedia(constraints, cb, errcb) {
                                navigator.mediaDevices.getUserMedia(constraints).then(cb, errcb)
                            }.bind(navigator)
                        }
                    }

                    function shimConstraints(constraints) {
                        if (constraints && constraints.video !== undefined) {
                            return Object.assign({}, constraints, {
                                video: utils.compactObject(constraints.video)
                            })
                        }

                        return constraints
                    }

                    function shimRTCIceServerUrls(window) {
                        if (!window.RTCPeerConnection) {
                            return
                        }
                        // migrate from non-spec RTCIceServer.url to RTCIceServer.urls
                        var OrigPeerConnection = window.RTCPeerConnection
                        window.RTCPeerConnection = function RTCPeerConnection(pcConfig, pcConstraints) {
                            if (pcConfig && pcConfig.iceServers) {
                                var newIceServers = []
                                for (var i = 0; i < pcConfig.iceServers.length; i++) {
                                    var server = pcConfig.iceServers[i]
                                    if (!server.hasOwnProperty('urls') && server.hasOwnProperty('url')) {
                                        utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls')
                                        server = JSON.parse(JSON.stringify(server))
                                        server.urls = server.url
                                        delete server.url
                                        newIceServers.push(server)
                                    } else {
                                        newIceServers.push(pcConfig.iceServers[i])
                                    }
                                }
                                pcConfig.iceServers = newIceServers
                            }
                            return new OrigPeerConnection(pcConfig, pcConstraints)
                        }
                        window.RTCPeerConnection.prototype = OrigPeerConnection.prototype
                        // wrap static methods. Currently just generateCertificate.
                        if ('generateCertificate' in OrigPeerConnection) {
                            Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
                                get: function get() {
                                    return OrigPeerConnection.generateCertificate
                                }
                            })
                        }
                    }

                    function shimTrackEventTransceiver(window) {
                        // Add event.transceiver member over deprecated event.receiver
                        if (
                            (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' &&
                            window.RTCTrackEvent &&
                            'receiver' in window.RTCTrackEvent.prototype &&
                            !('transceiver' in window.RTCTrackEvent.prototype)
                        ) {
                            Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {
                                get: function get() {
                                    return { receiver: this.receiver }
                                }
                            })
                        }
                    }

                    function shimCreateOfferLegacy(window) {
                        var origCreateOffer = window.RTCPeerConnection.prototype.createOffer
                        window.RTCPeerConnection.prototype.createOffer = function createOffer(offerOptions) {
                            if (offerOptions) {
                                if (typeof offerOptions.offerToReceiveAudio !== 'undefined') {
                                    // support bit values
                                    offerOptions.offerToReceiveAudio = !!offerOptions.offerToReceiveAudio
                                }
                                var audioTransceiver = this.getTransceivers().find(function (transceiver) {
                                    return transceiver.receiver.track.kind === 'audio'
                                })
                                if (offerOptions.offerToReceiveAudio === false && audioTransceiver) {
                                    if (audioTransceiver.direction === 'sendrecv') {
                                        if (audioTransceiver.setDirection) {
                                            audioTransceiver.setDirection('sendonly')
                                        } else {
                                            audioTransceiver.direction = 'sendonly'
                                        }
                                    } else if (audioTransceiver.direction === 'recvonly') {
                                        if (audioTransceiver.setDirection) {
                                            audioTransceiver.setDirection('inactive')
                                        } else {
                                            audioTransceiver.direction = 'inactive'
                                        }
                                    }
                                } else if (offerOptions.offerToReceiveAudio === true && !audioTransceiver) {
                                    this.addTransceiver('audio', { direction: 'recvonly' })
                                }

                                if (typeof offerOptions.offerToReceiveVideo !== 'undefined') {
                                    // support bit values
                                    offerOptions.offerToReceiveVideo = !!offerOptions.offerToReceiveVideo
                                }
                                var videoTransceiver = this.getTransceivers().find(function (transceiver) {
                                    return transceiver.receiver.track.kind === 'video'
                                })
                                if (offerOptions.offerToReceiveVideo === false && videoTransceiver) {
                                    if (videoTransceiver.direction === 'sendrecv') {
                                        if (videoTransceiver.setDirection) {
                                            videoTransceiver.setDirection('sendonly')
                                        } else {
                                            videoTransceiver.direction = 'sendonly'
                                        }
                                    } else if (videoTransceiver.direction === 'recvonly') {
                                        if (videoTransceiver.setDirection) {
                                            videoTransceiver.setDirection('inactive')
                                        } else {
                                            videoTransceiver.direction = 'inactive'
                                        }
                                    }
                                } else if (offerOptions.offerToReceiveVideo === true && !videoTransceiver) {
                                    this.addTransceiver('video', { direction: 'recvonly' })
                                }
                            }
                            return origCreateOffer.apply(this, arguments)
                        }
                    }

                    function shimAudioContext(window) {
                        if (
                            (typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== 'object' ||
                            window.AudioContext
                        ) {
                            return
                        }
                        window.AudioContext = window.webkitAudioContext
                    }
                },
                { '../utils': 11 }
            ],
            11: [
                function (require, module, exports) {
                    /*
                     *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
                     *
                     *  Use of this source code is governed by a BSD-style license
                     *  that can be found in the LICENSE file in the root of the source
                     *  tree.
                     */
                    /* eslint-env node */
                    'use strict'

                    Object.defineProperty(exports, '__esModule', {
                        value: true
                    })

                    var _typeof =
                        typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol'
                            ? function (obj) {
                                return typeof obj
                            }
                            : function (obj) {
                                return obj &&
                                    typeof Symbol === 'function' &&
                                    obj.constructor === Symbol &&
                                    obj !== Symbol.prototype
                                    ? 'symbol'
                                    : typeof obj
                            }

                    exports.extractVersion = extractVersion
                    exports.wrapPeerConnectionEvent = wrapPeerConnectionEvent
                    exports.disableLog = disableLog
                    exports.disableWarnings = disableWarnings
                    exports.log = log
                    exports.deprecated = deprecated
                    exports.detectBrowser = detectBrowser
                    exports.compactObject = compactObject
                    exports.walkStats = walkStats
                    exports.filterStats = filterStats

                    function _defineProperty(obj, key, value) {
                        if (key in obj) {
                            Object.defineProperty(obj, key, {
                                value: value,
                                enumerable: true,
                                configurable: true,
                                writable: true
                            })
                        } else {
                            obj[key] = value
                        }
                        return obj
                    }

                    var logDisabled_ = true
                    var deprecationWarnings_ = true

                    /**
                     * Extract browser version out of the provided user agent string.
                     *
                     * @param {!string} uastring userAgent string.
                     * @param {!string} expr Regular expression used as match criteria.
                     * @param {!number} pos position in the version string to be returned.
                     * @return {!number} browser version.
                     */
                    function extractVersion(uastring, expr, pos) {
                        var match = uastring.match(expr)
                        return match && match.length >= pos && parseInt(match[pos], 10)
                    }

                    // Wraps the peerconnection event eventNameToWrap in a function
                    // which returns the modified event object (or false to prevent
                    // the event).
                    function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) {
                        if (!window.RTCPeerConnection) {
                            return
                        }
                        var proto = window.RTCPeerConnection.prototype
                        var nativeAddEventListener = proto.addEventListener
                        proto.addEventListener = function (nativeEventName, cb) {
                            if (nativeEventName !== eventNameToWrap) {
                                return nativeAddEventListener.apply(this, arguments)
                            }
                            var wrappedCallback = function wrappedCallback(e) {
                                var modifiedEvent = wrapper(e)
                                if (modifiedEvent) {
                                    if (cb.handleEvent) {
                                        cb.handleEvent(modifiedEvent)
                                    } else {
                                        cb(modifiedEvent)
                                    }
                                }
                            }
                            this._eventMap = this._eventMap || {}
                            if (!this._eventMap[eventNameToWrap]) {
                                this._eventMap[eventNameToWrap] = new Map()
                            }
                            this._eventMap[eventNameToWrap].set(cb, wrappedCallback)
                            return nativeAddEventListener.apply(this, [nativeEventName, wrappedCallback])
                        }

                        var nativeRemoveEventListener = proto.removeEventListener
                        proto.removeEventListener = function (nativeEventName, cb) {
                            if (
                                nativeEventName !== eventNameToWrap ||
                                !this._eventMap ||
                                !this._eventMap[eventNameToWrap]
                            ) {
                                return nativeRemoveEventListener.apply(this, arguments)
                            }
                            if (!this._eventMap[eventNameToWrap].has(cb)) {
                                return nativeRemoveEventListener.apply(this, arguments)
                            }
                            var unwrappedCb = this._eventMap[eventNameToWrap].get(cb)
                            this._eventMap[eventNameToWrap].delete(cb)
                            if (this._eventMap[eventNameToWrap].size === 0) {
                                delete this._eventMap[eventNameToWrap]
                            }
                            if (Object.keys(this._eventMap).length === 0) {
                                delete this._eventMap
                            }
                            return nativeRemoveEventListener.apply(this, [nativeEventName, unwrappedCb])
                        }

                        Object.defineProperty(proto, 'on' + eventNameToWrap, {
                            get: function get() {
                                return this['_on' + eventNameToWrap]
                            },
                            set: function set(cb) {
                                if (this['_on' + eventNameToWrap]) {
                                    this.removeEventListener(eventNameToWrap, this['_on' + eventNameToWrap])
                                    delete this['_on' + eventNameToWrap]
                                }
                                if (cb) {
                                    this.addEventListener(eventNameToWrap, (this['_on' + eventNameToWrap] = cb))
                                }
                            },

                            enumerable: true,
                            configurable: true
                        })
                    }

                    function disableLog(bool) {
                        if (typeof bool !== 'boolean') {
                            return new Error(
                                'Argument type: ' +
                                (typeof bool === 'undefined' ? 'undefined' : _typeof(bool)) +
                                '. Please use a boolean.'
                            )
                        }
                        logDisabled_ = bool
                        return bool ? 'adapter.js logging disabled' : 'adapter.js logging enabled'
                    }

                    /**
                     * Disable or enable deprecation warnings
                     * @param {!boolean} bool set to true to disable warnings.
                     */
                    function disableWarnings(bool) {
                        if (typeof bool !== 'boolean') {
                            return new Error(
                                'Argument type: ' +
                                (typeof bool === 'undefined' ? 'undefined' : _typeof(bool)) +
                                '. Please use a boolean.'
                            )
                        }
                        deprecationWarnings_ = !bool
                        return 'adapter.js deprecation warnings ' + (bool ? 'disabled' : 'enabled')
                    }

                    function log() {
                        if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object') {
                            if (logDisabled_) {
                                return
                            }
                            if (typeof console !== 'undefined' && typeof console.log === 'function') {
                                console.log.apply(console, arguments)
                            }
                        }
                    }

                    /**
                     * Shows a deprecation warning suggesting the modern and spec-compatible API.
                     */
                    function deprecated(oldMethod, newMethod) {
                        if (!deprecationWarnings_) {
                            return
                        }
                        console.warn(oldMethod + ' is deprecated, please use ' + newMethod + ' instead.')
                    }

                    /**
                     * Browser detector.
                     *
                     * @return {object} result containing browser and version
                     *     properties.
                     */
                    function detectBrowser(window) {
                        // Returned result object.
                        var result = { browser: null, version: null }

                        // Fail early if it's not a browser
                        if (typeof window === 'undefined' || !window.navigator) {
                            result.browser = 'Not a browser.'
                            return result
                        }

                        var navigator = window.navigator

                        if (navigator.mozGetUserMedia) {
                            // Firefox.
                            result.browser = 'firefox'
                            result.version = extractVersion(navigator.userAgent, /Firefox\/(\d+)\./, 1)
                        } else if (
                            navigator.webkitGetUserMedia ||
                            (window.isSecureContext === false && window.webkitRTCPeerConnection)
                        ) {
                            // Chrome, Chromium, Webview, Opera.
                            // Version matches Chrome/WebRTC version.
                            // Chrome 74 removed webkitGetUserMedia on http as well so we need the
                            // more complicated fallback to webkitRTCPeerConnection.
                            result.browser = 'chrome'
                            result.version = extractVersion(navigator.userAgent, /Chrom(e|ium)\/(\d+)\./, 2)
                        } else if (
                            window.RTCPeerConnection &&
                            navigator.userAgent.match(/AppleWebKit\/(\d+)\./)
                        ) {
                            // Safari.
                            result.browser = 'safari'
                            result.version = extractVersion(navigator.userAgent, /AppleWebKit\/(\d+)\./, 1)
                            result.supportsUnifiedPlan =
                                window.RTCRtpTransceiver && 'currentDirection' in window.RTCRtpTransceiver.prototype
                        } else {
                            // Default fallthrough: not supported.
                            result.browser = 'Not a supported browser.'
                            return result
                        }

                        return result
                    }

                    /**
                     * Checks if something is an object.
                     *
                     * @param {*} val The something you want to check.
                     * @return true if val is an object, false otherwise.
                     */
                    function isObject(val) {
                        return Object.prototype.toString.call(val) === '[object Object]'
                    }

                    /**
                     * Remove all empty objects and undefined values
                     * from a nested object -- an enhanced and vanilla version
                     * of Lodash's `compact`.
                     */
                    function compactObject(data) {
                        if (!isObject(data)) {
                            return data
                        }

                        return Object.keys(data).reduce(function (accumulator, key) {
                            var isObj = isObject(data[key])
                            var value = isObj ? compactObject(data[key]) : data[key]
                            var isEmptyObject = isObj && !Object.keys(value).length
                            if (value === undefined || isEmptyObject) {
                                return accumulator
                            }
                            return Object.assign(accumulator, _defineProperty({}, key, value))
                        }, {})
                    }

                    /* iterates the stats graph recursively. */
                    function walkStats(stats, base, resultSet) {
                        if (!base || resultSet.has(base.id)) {
                            return
                        }
                        resultSet.set(base.id, base)
                        Object.keys(base).forEach(function (name) {
                            if (name.endsWith('Id')) {
                                walkStats(stats, stats.get(base[name]), resultSet)
                            } else if (name.endsWith('Ids')) {
                                base[name].forEach(function (id) {
                                    walkStats(stats, stats.get(id), resultSet)
                                })
                            }
                        })
                    }

                    /* filter getStats for a sender/receiver track. */
                    function filterStats(result, track, outbound) {
                        var streamStatsType = outbound ? 'outbound-rtp' : 'inbound-rtp'
                        var filteredResult = new Map()
                        if (track === null) {
                            return filteredResult
                        }
                        var trackStats = []
                        result.forEach(function (value) {
                            if (value.type === 'track' && value.trackIdentifier === track.id) {
                                trackStats.push(value)
                            }
                        })
                        trackStats.forEach(function (trackStat) {
                            result.forEach(function (stats) {
                                if (stats.type === streamStatsType && stats.trackId === trackStat.id) {
                                    walkStats(result, stats, filteredResult)
                                }
                            })
                        })
                        return filteredResult
                    }
                },
                {}
            ],
            12: [
                function (require, module, exports) {
                    /* eslint-env node */
                    'use strict'

                    // SDP helpers.

                    var _typeof =
                        typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol'
                            ? function (obj) {
                                return typeof obj
                            }
                            : function (obj) {
                                return obj &&
                                    typeof Symbol === 'function' &&
                                    obj.constructor === Symbol &&
                                    obj !== Symbol.prototype
                                    ? 'symbol'
                                    : typeof obj
                            }

                    var SDPUtils = {}

                    // Generate an alphanumeric identifier for cname or mids.
                    // TODO: use UUIDs instead? https://gist.github.com/jed/982883
                    SDPUtils.generateIdentifier = function () {
                        return Math.random().toString(36).substr(2, 10)
                    }

                    // The RTCP CNAME used by all peerconnections from the same JS.
                    SDPUtils.localCName = SDPUtils.generateIdentifier()

                    // Splits SDP into lines, dealing with both CRLF and LF.
                    SDPUtils.splitLines = function (blob) {
                        return blob
                            .trim()
                            .split('\n')
                            .map(function (line) {
                                return line.trim()
                            })
                    }
                    // Splits SDP into sessionpart and mediasections. Ensures CRLF.
                    SDPUtils.splitSections = function (blob) {
                        var parts = blob.split('\nm=')
                        return parts.map(function (part, index) {
                            return (index > 0 ? 'm=' + part : part).trim() + '\r\n'
                        })
                    }

                    // Returns the session description.
                    SDPUtils.getDescription = function (blob) {
                        var sections = SDPUtils.splitSections(blob)
                        return sections && sections[0]
                    }

                    // Returns the individual media sections.
                    SDPUtils.getMediaSections = function (blob) {
                        var sections = SDPUtils.splitSections(blob)
                        sections.shift()
                        return sections
                    }

                    // Returns lines that start with a certain prefix.
                    SDPUtils.matchPrefix = function (blob, prefix) {
                        return SDPUtils.splitLines(blob).filter(function (line) {
                            return line.indexOf(prefix) === 0
                        })
                    }

                    // Parses an ICE candidate line. Sample input:
                    // candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8
                    // rport 55996"
                    // Input can be prefixed with a=.
                    SDPUtils.parseCandidate = function (line) {
                        var parts = void 0
                        // Parse both variants.
                        if (line.indexOf('a=candidate:') === 0) {
                            parts = line.substring(12).split(' ')
                        } else {
                            parts = line.substring(10).split(' ')
                        }

                        var candidate = {
                            foundation: parts[0],
                            component: { 1: 'rtp', 2: 'rtcp' }[parts[1]] || parts[1],
                            protocol: parts[2].toLowerCase(),
                            priority: parseInt(parts[3], 10),
                            ip: parts[4],
                            address: parts[4], // address is an alias for ip.
                            port: parseInt(parts[5], 10),
                            // skip parts[6] == 'typ'
                            type: parts[7]
                        }

                        for (var i = 8; i < parts.length; i += 2) {
                            switch (parts[i]) {
                                case 'raddr':
                                    candidate.relatedAddress = parts[i + 1]
                                    break
                                case 'rport':
                                    candidate.relatedPort = parseInt(parts[i + 1], 10)
                                    break
                                case 'tcptype':
                                    candidate.tcpType = parts[i + 1]
                                    break
                                case 'ufrag':
                                    candidate.ufrag = parts[i + 1] // for backward compatibility.
                                    candidate.usernameFragment = parts[i + 1]
                                    break
                                default:
                                    // extension handling, in particular ufrag. Don't overwrite.
                                    if (candidate[parts[i]] === undefined) {
                                        candidate[parts[i]] = parts[i + 1]
                                    }
                                    break
                            }
                        }
                        return candidate
                    }

                    // Translates a candidate object into SDP candidate attribute.
                    // This does not include the a= prefix!
                    SDPUtils.writeCandidate = function (candidate) {
                        var sdp = []
                        sdp.push(candidate.foundation)

                        var component = candidate.component
                        if (component === 'rtp') {
                            sdp.push(1)
                        } else if (component === 'rtcp') {
                            sdp.push(2)
                        } else {
                            sdp.push(component)
                        }
                        sdp.push(candidate.protocol.toUpperCase())
                        sdp.push(candidate.priority)
                        sdp.push(candidate.address || candidate.ip)
                        sdp.push(candidate.port)

                        var type = candidate.type
                        sdp.push('typ')
                        sdp.push(type)
                        if (type !== 'host' && candidate.relatedAddress && candidate.relatedPort) {
                            sdp.push('raddr')
                            sdp.push(candidate.relatedAddress)
                            sdp.push('rport')
                            sdp.push(candidate.relatedPort)
                        }
                        if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') {
                            sdp.push('tcptype')
                            sdp.push(candidate.tcpType)
                        }
                        if (candidate.usernameFragment || candidate.ufrag) {
                            sdp.push('ufrag')
                            sdp.push(candidate.usernameFragment || candidate.ufrag)
                        }
                        return 'candidate:' + sdp.join(' ')
                    }

                    // Parses an ice-options line, returns an array of option tags.
                    // Sample input:
                    // a=ice-options:foo bar
                    SDPUtils.parseIceOptions = function (line) {
                        return line.substr(14).split(' ')
                    }

                    // Parses a rtpmap line, returns RTCRtpCoddecParameters. Sample input:
                    // a=rtpmap:111 opus/48000/2
                    SDPUtils.parseRtpMap = function (line) {
                        var parts = line.substr(9).split(' ')
                        var parsed = {
                            payloadType: parseInt(parts.shift(), 10) // was: id
                        }

                        parts = parts[0].split('/')

                        parsed.name = parts[0]
                        parsed.clockRate = parseInt(parts[1], 10) // was: clockrate
                        parsed.channels = parts.length === 3 ? parseInt(parts[2], 10) : 1
                        // legacy alias, got renamed back to channels in ORTC.
                        parsed.numChannels = parsed.channels
                        return parsed
                    }

                    // Generates a rtpmap line from RTCRtpCodecCapability or
                    // RTCRtpCodecParameters.
                    SDPUtils.writeRtpMap = function (codec) {
                        var pt = codec.payloadType
                        if (codec.preferredPayloadType !== undefined) {
                            pt = codec.preferredPayloadType
                        }
                        var channels = codec.channels || codec.numChannels || 1
                        return (
                            'a=rtpmap:' +
                            pt +
                            ' ' +
                            codec.name +
                            '/' +
                            codec.clockRate +
                            (channels !== 1 ? '/' + channels : '') +
                            '\r\n'
                        )
                    }

                    // Parses a extmap line (headerextension from RFC 5285). Sample input:
                    // a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
                    // a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset
                    SDPUtils.parseExtmap = function (line) {
                        var parts = line.substr(9).split(' ')
                        return {
                            id: parseInt(parts[0], 10),
                            direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv',
                            uri: parts[1]
                        }
                    }

                    // Generates an extmap line from RTCRtpHeaderExtensionParameters or
                    // RTCRtpHeaderExtension.
                    SDPUtils.writeExtmap = function (headerExtension) {
                        return (
                            'a=extmap:' +
                            (headerExtension.id || headerExtension.preferredId) +
                            (headerExtension.direction && headerExtension.direction !== 'sendrecv'
                                ? '/' + headerExtension.direction
                                : '') +
                            ' ' +
                            headerExtension.uri +
                            '\r\n'
                        )
                    }

                    // Parses a fmtp line, returns dictionary. Sample input:
                    // a=fmtp:96 vbr=on;cng=on
                    // Also deals with vbr=on; cng=on
                    SDPUtils.parseFmtp = function (line) {
                        var parsed = {}
                        var kv = void 0
                        var parts = line.substr(line.indexOf(' ') + 1).split(';')
                        for (var j = 0; j < parts.length; j++) {
                            kv = parts[j].trim().split('=')
                            parsed[kv[0].trim()] = kv[1]
                        }
                        return parsed
                    }

                    // Generates a fmtp line from RTCRtpCodecCapability or RTCRtpCodecParameters.
                    SDPUtils.writeFmtp = function (codec) {
                        var line = ''
                        var pt = codec.payloadType
                        if (codec.preferredPayloadType !== undefined) {
                            pt = codec.preferredPayloadType
                        }
                        if (codec.parameters && Object.keys(codec.parameters).length) {
                            var params = []
                            Object.keys(codec.parameters).forEach(function (param) {
                                if (codec.parameters[param] !== undefined) {
                                    params.push(param + '=' + codec.parameters[param])
                                } else {
                                    params.push(param)
                                }
                            })
                            line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\r\n'
                        }
                        return line
                    }

                    // Parses a rtcp-fb line, returns RTCPRtcpFeedback object. Sample input:
                    // a=rtcp-fb:98 nack rpsi
                    SDPUtils.parseRtcpFb = function (line) {
                        var parts = line.substr(line.indexOf(' ') + 1).split(' ')
                        return {
                            type: parts.shift(),
                            parameter: parts.join(' ')
                        }
                    }

                    // Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters.
                    SDPUtils.writeRtcpFb = function (codec) {
                        var lines = ''
                        var pt = codec.payloadType
                        if (codec.preferredPayloadType !== undefined) {
                            pt = codec.preferredPayloadType
                        }
                        if (codec.rtcpFeedback && codec.rtcpFeedback.length) {
                            // FIXME: special handling for trr-int?
                            codec.rtcpFeedback.forEach(function (fb) {
                                lines +=
                                    'a=rtcp-fb:' +
                                    pt +
                                    ' ' +
                                    fb.type +
                                    (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') +
                                    '\r\n'
                            })
                        }
                        return lines
                    }

                    // Parses a RFC 5576 ssrc media attribute. Sample input:
                    // a=ssrc:3735928559 cname:something
                    SDPUtils.parseSsrcMedia = function (line) {
                        var sp = line.indexOf(' ')
                        var parts = {
                            ssrc: parseInt(line.substr(7, sp - 7), 10)
                        }
                        var colon = line.indexOf(':', sp)
                        if (colon > -1) {
                            parts.attribute = line.substr(sp + 1, colon - sp - 1)
                            parts.value = line.substr(colon + 1)
                        } else {
                            parts.attribute = line.substr(sp + 1)
                        }
                        return parts
                    }

                    // Parse a ssrc-group line (see RFC 5576). Sample input:
                    // a=ssrc-group:semantics 12 34
                    SDPUtils.parseSsrcGroup = function (line) {
                        var parts = line.substr(13).split(' ')
                        return {
                            semantics: parts.shift(),
                            ssrcs: parts.map(function (ssrc) {
                                return parseInt(ssrc, 10)
                            })
                        }
                    }

                    // Extracts the MID (RFC 5888) from a media section.
                    // Returns the MID or undefined if no mid line was found.
                    SDPUtils.getMid = function (mediaSection) {
                        var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0]
                        if (mid) {
                            return mid.substr(6)
                        }
                    }

                    // Parses a fingerprint line for DTLS-SRTP.
                    SDPUtils.parseFingerprint = function (line) {
                        var parts = line.substr(14).split(' ')
                        return {
                            algorithm: parts[0].toLowerCase(), // algorithm is case-sensitive in Edge.
                            value: parts[1].toUpperCase() // the definition is upper-case in RFC 4572.
                        }
                    }

                    // Extracts DTLS parameters from SDP media section or sessionpart.
                    // FIXME: for consistency with other functions this should only
                    //   get the fingerprint line as input. See also getIceParameters.
                    SDPUtils.getDtlsParameters = function (mediaSection, sessionpart) {
                        var lines = SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=fingerprint:')
                        // Note: a=setup line is ignored since we use the 'auto' role in Edge.
                        return {
                            role: 'auto',
                            fingerprints: lines.map(SDPUtils.parseFingerprint)
                        }
                    }

                    // Serializes DTLS parameters to SDP.
                    SDPUtils.writeDtlsParameters = function (params, setupType) {
                        var sdp = 'a=setup:' + setupType + '\r\n'
                        params.fingerprints.forEach(function (fp) {
                            sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\r\n'
                        })
                        return sdp
                    }

                    // Parses a=crypto lines into
                    //   https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#dictionary-rtcsrtpsdesparameters-members
                    SDPUtils.parseCryptoLine = function (line) {
                        var parts = line.substr(9).split(' ')
                        return {
                            tag: parseInt(parts[0], 10),
                            cryptoSuite: parts[1],
                            keyParams: parts[2],
                            sessionParams: parts.slice(3)
                        }
                    }

                    SDPUtils.writeCryptoLine = function (parameters) {
                        return (
                            'a=crypto:' +
                            parameters.tag +
                            ' ' +
                            parameters.cryptoSuite +
                            ' ' +
                            (_typeof(parameters.keyParams) === 'object'
                                ? SDPUtils.writeCryptoKeyParams(parameters.keyParams)
                                : parameters.keyParams) +
                            (parameters.sessionParams ? ' ' + parameters.sessionParams.join(' ') : '') +
                            '\r\n'
                        )
                    }

                    // Parses the crypto key parameters into
                    //   https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#rtcsrtpkeyparam*
                    SDPUtils.parseCryptoKeyParams = function (keyParams) {
                        if (keyParams.indexOf('inline:') !== 0) {
                            return null
                        }
                        var parts = keyParams.substr(7).split('|')
                        return {
                            keyMethod: 'inline',
                            keySalt: parts[0],
                            lifeTime: parts[1],
                            mkiValue: parts[2] ? parts[2].split(':')[0] : undefined,
                            mkiLength: parts[2] ? parts[2].split(':')[1] : undefined
                        }
                    }

                    SDPUtils.writeCryptoKeyParams = function (keyParams) {
                        return (
                            keyParams.keyMethod +
                            ':' +
                            keyParams.keySalt +
                            (keyParams.lifeTime ? '|' + keyParams.lifeTime : '') +
                            (keyParams.mkiValue && keyParams.mkiLength
                                ? '|' + keyParams.mkiValue + ':' + keyParams.mkiLength
                                : '')
                        )
                    }

                    // Extracts all SDES parameters.
                    SDPUtils.getCryptoParameters = function (mediaSection, sessionpart) {
                        var lines = SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=crypto:')
                        return lines.map(SDPUtils.parseCryptoLine)
                    }

                    // Parses ICE information from SDP media section or sessionpart.
                    // FIXME: for consistency with other functions this should only
                    //   get the ice-ufrag and ice-pwd lines as input.
                    SDPUtils.getIceParameters = function (mediaSection, sessionpart) {
                        var ufrag = SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=ice-ufrag:')[0]
                        var pwd = SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=ice-pwd:')[0]
                        if (!(ufrag && pwd)) {
                            return null
                        }
                        return {
                            usernameFragment: ufrag.substr(12),
                            password: pwd.substr(10)
                        }
                    }

                    // Serializes ICE parameters to SDP.
                    SDPUtils.writeIceParameters = function (params) {
                        var sdp =
                            'a=ice-ufrag:' +
                            params.usernameFragment +
                            '\r\n' +
                            'a=ice-pwd:' +
                            params.password +
                            '\r\n'
                        if (params.iceLite) {
                            sdp += 'a=ice-lite\r\n'
                        }
                        return sdp
                    }

                    // Parses the SDP media section and returns RTCRtpParameters.
                    SDPUtils.parseRtpParameters = function (mediaSection) {
                        var description = {
                            codecs: [],
                            headerExtensions: [],
                            fecMechanisms: [],
                            rtcp: []
                        }
                        var lines = SDPUtils.splitLines(mediaSection)
                        var mline = lines[0].split(' ')
                        for (var i = 3; i < mline.length; i++) {
                            // find all codecs from mline[3..]
                            var pt = mline[i]
                            var rtpmapline = SDPUtils.matchPrefix(mediaSection, 'a=rtpmap:' + pt + ' ')[0]
                            if (rtpmapline) {
                                var codec = SDPUtils.parseRtpMap(rtpmapline)
                                var fmtps = SDPUtils.matchPrefix(mediaSection, 'a=fmtp:' + pt + ' ')
                                // Only the first a=fmtp:<pt> is considered.
                                codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {}
                                codec.rtcpFeedback = SDPUtils.matchPrefix(
                                    mediaSection,
                                    'a=rtcp-fb:' + pt + ' '
                                ).map(SDPUtils.parseRtcpFb)
                                description.codecs.push(codec)
                                // parse FEC mechanisms from rtpmap lines.
                                switch (codec.name.toUpperCase()) {
                                    case 'RED':
                                    case 'ULPFEC':
                                        description.fecMechanisms.push(codec.name.toUpperCase())
                                        break
                                    default:
                                        // only RED and ULPFEC are recognized as FEC mechanisms.
                                        break
                                }
                            }
                        }
                        SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(function (line) {
                            description.headerExtensions.push(SDPUtils.parseExtmap(line))
                        })
                        // FIXME: parse rtcp.
                        return description
                    }

                    // Generates parts of the SDP media section describing the capabilities /
                    // parameters.
                    SDPUtils.writeRtpDescription = function (kind, caps) {
                        var sdp = ''

                        // Build the mline.
                        sdp += 'm=' + kind + ' '
                        sdp += caps.codecs.length > 0 ? '9' : '0' // reject if no codecs.
                        sdp += ' UDP/TLS/RTP/SAVPF '
                        sdp +=
                            caps.codecs
                                .map(function (codec) {
                                    if (codec.preferredPayloadType !== undefined) {
                                        return codec.preferredPayloadType
                                    }
                                    return codec.payloadType
                                })
                                .join(' ') + '\r\n'

                        sdp += 'c=IN IP4 0.0.0.0\r\n'
                        sdp += 'a=rtcp:9 IN IP4 0.0.0.0\r\n'

                        // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb.
                        caps.codecs.forEach(function (codec) {
                            sdp += SDPUtils.writeRtpMap(codec)
                            sdp += SDPUtils.writeFmtp(codec)
                            sdp += SDPUtils.writeRtcpFb(codec)
                        })
                        var maxptime = 0
                        caps.codecs.forEach(function (codec) {
                            if (codec.maxptime > maxptime) {
                                maxptime = codec.maxptime
                            }
                        })
                        if (maxptime > 0) {
                            sdp += 'a=maxptime:' + maxptime + '\r\n'
                        }

                        if (caps.headerExtensions) {
                            caps.headerExtensions.forEach(function (extension) {
                                sdp += SDPUtils.writeExtmap(extension)
                            })
                        }
                        // FIXME: write fecMechanisms.
                        return sdp
                    }

                    // Parses the SDP media section and returns an array of
                    // RTCRtpEncodingParameters.
                    SDPUtils.parseRtpEncodingParameters = function (mediaSection) {
                        var encodingParameters = []
                        var description = SDPUtils.parseRtpParameters(mediaSection)
                        var hasRed = description.fecMechanisms.indexOf('RED') !== -1
                        var hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1

                        // filter a=ssrc:... cname:, ignore PlanB-msid
                        var ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
                            .map(function (line) {
                                return SDPUtils.parseSsrcMedia(line)
                            })
                            .filter(function (parts) {
                                return parts.attribute === 'cname'
                            })
                        var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc
                        var secondarySsrc = void 0

                        var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID').map(function (line) {
                            var parts = line.substr(17).split(' ')
                            return parts.map(function (part) {
                                return parseInt(part, 10)
                            })
                        })
                        if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) {
                            secondarySsrc = flows[0][1]
                        }

                        description.codecs.forEach(function (codec) {
                            if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) {
                                var encParam = {
                                    ssrc: primarySsrc,
                                    codecPayloadType: parseInt(codec.parameters.apt, 10)
                                }
                                if (primarySsrc && secondarySsrc) {
                                    encParam.rtx = { ssrc: secondarySsrc }
                                }
                                encodingParameters.push(encParam)
                                if (hasRed) {
                                    encParam = JSON.parse(JSON.stringify(encParam))
                                    encParam.fec = {
                                        ssrc: primarySsrc,
                                        mechanism: hasUlpfec ? 'red+ulpfec' : 'red'
                                    }
                                    encodingParameters.push(encParam)
                                }
                            }
                        })
                        if (encodingParameters.length === 0 && primarySsrc) {
                            encodingParameters.push({
                                ssrc: primarySsrc
                            })
                        }

                        // we support both b=AS and b=TIAS but interpret AS as TIAS.
                        var bandwidth = SDPUtils.matchPrefix(mediaSection, 'b=')
                        if (bandwidth.length) {
                            if (bandwidth[0].indexOf('b=TIAS:') === 0) {
                                bandwidth = parseInt(bandwidth[0].substr(7), 10)
                            } else if (bandwidth[0].indexOf('b=AS:') === 0) {
                                // use formula from JSEP to convert b=AS to TIAS value.
                                bandwidth = parseInt(bandwidth[0].substr(5), 10) * 1000 * 0.95 - 50 * 40 * 8
                            } else {
                                bandwidth = undefined
                            }
                            encodingParameters.forEach(function (params) {
                                params.maxBitrate = bandwidth
                            })
                        }
                        return encodingParameters
                    }

                    // parses http://draft.ortc.org/#rtcrtcpparameters*
                    SDPUtils.parseRtcpParameters = function (mediaSection) {
                        var rtcpParameters = {}

                        // Gets the first SSRC. Note that with RTX there might be multiple
                        // SSRCs.
                        var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
                            .map(function (line) {
                                return SDPUtils.parseSsrcMedia(line)
                            })
                            .filter(function (obj) {
                                return obj.attribute === 'cname'
                            })[0]
                        if (remoteSsrc) {
                            rtcpParameters.cname = remoteSsrc.value
                            rtcpParameters.ssrc = remoteSsrc.ssrc
                        }

                        // Edge uses the compound attribute instead of reducedSize
                        // compound is !reducedSize
                        var rsize = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize')
                        rtcpParameters.reducedSize = rsize.length > 0
                        rtcpParameters.compound = rsize.length === 0

                        // parses the rtcp-mux attrіbute.
                        // Note that Edge does not support unmuxed RTCP.
                        var mux = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux')
                        rtcpParameters.mux = mux.length > 0

                        return rtcpParameters
                    }

                    SDPUtils.writeRtcpParameters = function (rtcpParameters) {
                        var sdp = ''
                        if (rtcpParameters.reducedSize) {
                            sdp += 'a=rtcp-rsize\r\n'
                        }
                        if (rtcpParameters.mux) {
                            sdp += 'a=rtcp-mux\r\n'
                        }
                        if (rtcpParameters.ssrc !== undefined && rtcpParameters.cname) {
                            sdp += 'a=ssrc:' + rtcpParameters.ssrc + ' cname:' + rtcpParameters.cname + '\r\n'
                        }
                        return sdp
                    }

                    // parses either a=msid: or a=ssrc:... msid lines and returns
                    // the id of the MediaStream and MediaStreamTrack.
                    SDPUtils.parseMsid = function (mediaSection) {
                        var parts = void 0
                        var spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:')
                        if (spec.length === 1) {
                            parts = spec[0].substr(7).split(' ')
                            return { stream: parts[0], track: parts[1] }
                        }
                        var planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
                            .map(function (line) {
                                return SDPUtils.parseSsrcMedia(line)
                            })
                            .filter(function (msidParts) {
                                return msidParts.attribute === 'msid'
                            })
                        if (planB.length > 0) {
                            parts = planB[0].value.split(' ')
                            return { stream: parts[0], track: parts[1] }
                        }
                    }

                    // SCTP
                    // parses draft-ietf-mmusic-sctp-sdp-26 first and falls back
                    // to draft-ietf-mmusic-sctp-sdp-05
                    SDPUtils.parseSctpDescription = function (mediaSection) {
                        var mline = SDPUtils.parseMLine(mediaSection)
                        var maxSizeLine = SDPUtils.matchPrefix(mediaSection, 'a=max-message-size:')
                        var maxMessageSize = void 0
                        if (maxSizeLine.length > 0) {
                            maxMessageSize = parseInt(maxSizeLine[0].substr(19), 10)
                        }
                        if (isNaN(maxMessageSize)) {
                            maxMessageSize = 65536
                        }
                        var sctpPort = SDPUtils.matchPrefix(mediaSection, 'a=sctp-port:')
                        if (sctpPort.length > 0) {
                            return {
                                port: parseInt(sctpPort[0].substr(12), 10),
                                protocol: mline.fmt,
                                maxMessageSize: maxMessageSize
                            }
                        }
                        var sctpMapLines = SDPUtils.matchPrefix(mediaSection, 'a=sctpmap:')
                        if (sctpMapLines.length > 0) {
                            var parts = sctpMapLines[0].substr(10).split(' ')
                            return {
                                port: parseInt(parts[0], 10),
                                protocol: parts[1],
                                maxMessageSize: maxMessageSize
                            }
                        }
                    }

                    // SCTP
                    // outputs the draft-ietf-mmusic-sctp-sdp-26 version that all browsers
                    // support by now receiving in this format, unless we originally parsed
                    // as the draft-ietf-mmusic-sctp-sdp-05 format (indicated by the m-line
                    // protocol of DTLS/SCTP -- without UDP/ or TCP/)
                    SDPUtils.writeSctpDescription = function (media, sctp) {
                        var output = []
                        if (media.protocol !== 'DTLS/SCTP') {
                            output = [
                                'm=' + media.kind + ' 9 ' + media.protocol + ' ' + sctp.protocol + '\r\n',
                                'c=IN IP4 0.0.0.0\r\n',
                                'a=sctp-port:' + sctp.port + '\r\n'
                            ]
                        } else {
                            output = [
                                'm=' + media.kind + ' 9 ' + media.protocol + ' ' + sctp.port + '\r\n',
                                'c=IN IP4 0.0.0.0\r\n',
                                'a=sctpmap:' + sctp.port + ' ' + sctp.protocol + ' 65535\r\n'
                            ]
                        }
                        if (sctp.maxMessageSize !== undefined) {
                            output.push('a=max-message-size:' + sctp.maxMessageSize + '\r\n')
                        }
                        return output.join('')
                    }

                    // Generate a session ID for SDP.
                    // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-20#section-5.2.1
                    // recommends using a cryptographically random +ve 64-bit value
                    // but right now this should be acceptable and within the right range
                    SDPUtils.generateSessionId = function () {
                        return Math.random().toString().substr(2, 21)
                    }

                    // Write boiler plate for start of SDP
                    // sessId argument is optional - if not supplied it will
                    // be generated randomly
                    // sessVersion is optional and defaults to 2
                    // sessUser is optional and defaults to 'thisisadapterortc'
                    SDPUtils.writeSessionBoilerplate = function (sessId, sessVer, sessUser) {
                        var sessionId = void 0
                        var version = sessVer !== undefined ? sessVer : 2
                        if (sessId) {
                            sessionId = sessId
                        } else {
                            sessionId = SDPUtils.generateSessionId()
                        }
                        var user = sessUser || 'thisisadapterortc'
                        // FIXME: sess-id should be an NTP timestamp.
                        return (
                            'v=0\r\n' +
                            'o=' +
                            user +
                            ' ' +
                            sessionId +
                            ' ' +
                            version +
                            ' IN IP4 127.0.0.1\r\n' +
                            's=-\r\n' +
                            't=0 0\r\n'
                        )
                    }

                    // Gets the direction from the mediaSection or the sessionpart.
                    SDPUtils.getDirection = function (mediaSection, sessionpart) {
                        // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv.
                        var lines = SDPUtils.splitLines(mediaSection)
                        for (var i = 0; i < lines.length; i++) {
                            switch (lines[i]) {
                                case 'a=sendrecv':
                                case 'a=sendonly':
                                case 'a=recvonly':
                                case 'a=inactive':
                                    return lines[i].substr(2)
                                default:
                                // FIXME: What should happen here?
                            }
                        }
                        if (sessionpart) {
                            return SDPUtils.getDirection(sessionpart)
                        }
                        return 'sendrecv'
                    }

                    SDPUtils.getKind = function (mediaSection) {
                        var lines = SDPUtils.splitLines(mediaSection)
                        var mline = lines[0].split(' ')
                        return mline[0].substr(2)
                    }

                    SDPUtils.isRejected = function (mediaSection) {
                        return mediaSection.split(' ', 2)[1] === '0'
                    }

                    SDPUtils.parseMLine = function (mediaSection) {
                        var lines = SDPUtils.splitLines(mediaSection)
                        var parts = lines[0].substr(2).split(' ')
                        return {
                            kind: parts[0],
                            port: parseInt(parts[1], 10),
                            protocol: parts[2],
                            fmt: parts.slice(3).join(' ')
                        }
                    }

                    SDPUtils.parseOLine = function (mediaSection) {
                        var line = SDPUtils.matchPrefix(mediaSection, 'o=')[0]
                        var parts = line.substr(2).split(' ')
                        return {
                            username: parts[0],
                            sessionId: parts[1],
                            sessionVersion: parseInt(parts[2], 10),
                            netType: parts[3],
                            addressType: parts[4],
                            address: parts[5]
                        }
                    }

                    // a very naive interpretation of a valid SDP.
                    SDPUtils.isValidSDP = function (blob) {
                        if (typeof blob !== 'string' || blob.length === 0) {
                            return false
                        }
                        var lines = SDPUtils.splitLines(blob)
                        for (var i = 0; i < lines.length; i++) {
                            if (lines[i].length < 2 || lines[i].charAt(1) !== '=') {
                                return false
                            }
                            // TODO: check the modifier a bit more.
                        }
                        return true
                    }

                    // Expose public methods.
                    if ((typeof module === 'undefined' ? 'undefined' : _typeof(module)) === 'object') {
                        module.exports = SDPUtils
                    }
                },
                {}
            ]
        },
        {},
        [1]
    )(1)
})
